diff options
Diffstat (limited to 'src/gui/platforms/s60')
23 files changed, 0 insertions, 11216 deletions
diff --git a/src/gui/platforms/s60/qapplication_s60.cpp b/src/gui/platforms/s60/qapplication_s60.cpp deleted file mode 100644 index 408c3b5883..0000000000 --- a/src/gui/platforms/s60/qapplication_s60.cpp +++ /dev/null @@ -1,2712 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication_p.h" -#include "qsessionmanager.h" -#include "qevent.h" -#include "qsymbianevent.h" -#include "qeventdispatcher_s60_p.h" -#include "qwidget.h" -#include "qdesktopwidget.h" -#include "private/qbackingstore_p.h" -#include "qt_s60_p.h" -#include "private/qevent_p.h" -#include "qstring.h" -#include "qdebug.h" -#include "qimage.h" -#include "qcombobox.h" -#include "private/qkeymapper_p.h" -#include "private/qfont_p.h" -#ifndef QT_NO_STYLE_S60 -#include "private/qs60style_p.h" -#endif -#include "private/qwindowsurface_s60_p.h" -#include "qpaintengine.h" -#include "private/qmenubar_p.h" -#include "private/qsoftkeymanager_p.h" -#ifdef QT_GRAPHICSSYSTEM_RUNTIME -#include "private/qgraphicssystem_runtime_p.h" -#endif - -#include "apgwgnam.h" // For CApaWindowGroupName -#include <mdaaudiotoneplayer.h> // For CMdaAudioToneUtility - -#if defined(Q_OS_SYMBIAN) -# include <private/qs60mainapplication_p.h> -# include <centralrepository.h> -# include "qs60mainappui.h" -# include "qinputcontext.h" -#endif - -#if defined(Q_WS_S60) -# if !defined(QT_NO_IM) -# include <private/qcoefepinputcontext_p.h> -# endif -#endif - -#include "private/qstylesheetstyle_p.h" - -#include <hal.h> -#include <hal_data.h> - -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS -#include <graphics/wstfxconst.h> -#endif - -QT_BEGIN_NAMESPACE - -// Goom Events through Window Server -static const int KGoomMemoryLowEvent = 0x10282DBF; -static const int KGoomMemoryGoodEvent = 0x20026790; -// Split view open/close events from AVKON -static const int KSplitViewOpenEvent = 0x2001E2C0; -static const int KSplitViewCloseEvent = 0x2001E2C1; - -#if defined(QT_DEBUG) -static bool appNoGrab = false; // Grabbing enabled -#endif -static bool app_do_modal = false; // modal mode -Q_GLOBAL_STATIC(QS60Data, qt_s60Data); - -extern bool qt_sendSpontaneousEvent(QObject*,QEvent*); -extern QWidgetList *qt_modal_stack; // stack of modal widgets -extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp - -QWidget *qt_button_down = 0; // widget got last button-down - -QSymbianControl *QSymbianControl::lastFocusedControl = 0; - -QS60Data* qGlobalS60Data() -{ - return qt_s60Data(); -} - -#ifdef Q_WS_S60 -void QS60Data::setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible) -{ - bool buttonGroupVisibilityChanged = false; - if (CEikButtonGroupContainer *const b = buttonGroupContainer()) { - buttonGroupVisibilityChanged = (b->IsVisible() != buttonGroupVisible); - b->MakeVisible(buttonGroupVisible); - } - bool statusPaneVisibilityChanged = false; - if (CEikStatusPane *const s = statusPane()) { - statusPaneVisibilityChanged = (s->IsVisible() != statusPaneVisible); - s->MakeVisible(statusPaneVisible); - } - if (buttonGroupVisibilityChanged || statusPaneVisibilityChanged) { - const QSize size = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()).size(); - const QSize oldSize; // note that QDesktopWidget::resizeEvent ignores the QResizeEvent contents - QResizeEvent event(size, oldSize); - QApplication::instance()->sendEvent(QApplication::desktop(), &event); - } - if (buttonGroupVisibilityChanged && !statusPaneVisibilityChanged && QApplication::activeWindow()) - // Ensure that control rectangle is updated - static_cast<QSymbianControl *>(QApplication::activeWindow()->winId())->handleClientAreaChange(); -} - -bool QS60Data::setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState) -{ - // Show statusbar: - // Topmost parent: Show unless fullscreen/minimized. - // Child windows: Follow topmost parent, unless fullscreen, in which case do not show statusbar - // Show CBA: - // Topmost parent: Show unless fullscreen/minimized. - // Exception: Show if fullscreen with Qt::WindowSoftkeysVisibleHint. - // Child windows: - // Minimized: Unclear if there is an use case for having focused minimized window at all. - // Always follow topmost parent just to be safe. - // Maximized and normal: follow topmost parent. - // Exception: If topmost parent is not showing CBA, show CBA if any softkey actions are - // defined. - // Fullscreen: Show only if Qt::WindowSoftkeysVisibleHint set. - - Qt::WindowStates comparisonState = newState; - QWidget *parentWindow = window->parentWidget(); - if (parentWindow) { - while (parentWindow->parentWidget()) - parentWindow = parentWindow->parentWidget(); - comparisonState = parentWindow->windowState(); - } else { - parentWindow = window; - } - - bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen; - const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint; - bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint)); - - // Do extra checking for child windows - if (window->parentWidget()) { - if (newState & Qt::WindowFullScreen) { - decorationsVisible = false; - if (window->windowFlags() & Qt::WindowSoftkeysVisibleHint) - buttonGroupVisibility = true; - else - buttonGroupVisibility = false; - } else if (!(newState & Qt::WindowMinimized) && !buttonGroupVisibility) { - for (int i = 0; i < window->actions().size(); ++i) { - if (window->actions().at(i)->softKeyRole() != QAction::NoSoftKey) { - buttonGroupVisibility = true; - break; - } - } - } - } - - S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility); - - return decorationsVisible; -} -#endif - -void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) -{ - if (QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control)) { - QWidget *const widget = QWidgetPrivate::mapper->value(control); - QWidget *const window = widget->window(); - if (QTLWExtra *topData = qt_widget_private(window)->maybeTopData()) { - QWidgetBackingStoreTracker &backingStore = topData->backingStore; - if (visible) { - if (backingStore.data()) { - backingStore.registerWidget(widget); - } else { - backingStore.create(window); - backingStore.registerWidget(widget); - qt_widget_private(widget)->invalidateBuffer(widget->rect()); - widget->repaint(); - } - } else { - // In certain special scenarios we may get an ENotVisible event - // without a previous EPartiallyVisible. The backingstore must - // still be destroyed, hence the registerWidget() call below. - if (backingStore.data() && widget->internalWinId() - && qt_widget_private(widget)->maybeBackingStore() == backingStore.data()) - backingStore.registerWidget(widget); - backingStore.unregisterWidget(widget); - // In order to ensure that any resources used by the window surface - // are immediately freed, we flush the WSERV command buffer. - S60->wsSession().Flush(); - } - } - } -} - -bool qt_nograb() // application no-grab option -{ -#if defined(QT_DEBUG) - return appNoGrab; -#else - return false; -#endif -} - -// Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument -class QS60Beep : public CBase, public MMdaAudioToneObserver -{ -public: - static QS60Beep* NewL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration); - void Play(); - ~QS60Beep(); -private: - void ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration); - void MatoPrepareComplete(TInt aError); - void MatoPlayComplete(TInt aError); -private: - typedef enum - { - EBeepNotPrepared, - EBeepPrepared, - EBeepPlaying - } TBeepState; -private: - CMdaAudioToneUtility* iToneUtil; - TBeepState iState; - TInt iFrequency; - TTimeIntervalMicroSeconds iDuration; -}; - -static QS60Beep* qt_S60Beep = 0; - -QS60Beep::~QS60Beep() -{ - if (iToneUtil) { - switch (iState) { - case EBeepPlaying: - iToneUtil->CancelPlay(); - break; - case EBeepNotPrepared: - iToneUtil->CancelPrepare(); - break; - } - } - delete iToneUtil; -} - -QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) -{ - QS60Beep* self = new (ELeave) QS60Beep(); - CleanupStack::PushL(self); - self->ConstructL(aFrequency, aDuration); - CleanupStack::Pop(); - return self; -} - -void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration) -{ - iToneUtil = CMdaAudioToneUtility::NewL(*this); - iState = EBeepNotPrepared; - iFrequency = aFrequency; - iDuration = aDuration; - iToneUtil->PrepareToPlayTone(iFrequency, iDuration); -} - -void QS60Beep::Play() -{ - if (iState == EBeepPlaying) { - iToneUtil->CancelPlay(); - iState = EBeepPrepared; - } - - iToneUtil->Play(); - iState = EBeepPlaying; -} - -void QS60Beep::MatoPrepareComplete(TInt aError) -{ - if (aError == KErrNone) { - iState = EBeepPrepared; - Play(); - } -} - -void QS60Beep::MatoPlayComplete(TInt aError) -{ - Q_UNUSED(aError); - iState = EBeepPrepared; -} - - -static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers) -{ - Qt::KeyboardModifiers result = Qt::NoModifier; - - if (s60Modifiers & EModifierKeypad) - result |= Qt::KeypadModifier; - if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift - || s60Modifiers & EModifierRightShift) - result |= Qt::ShiftModifier; - if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl - || s60Modifiers & EModifierRightCtrl) - result |= Qt::ControlModifier; - if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt - || s60Modifiers & EModifierRightAlt) - result |= Qt::AltModifier; - - return result; -} - -static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent) -{ - switch (pEvent->iType) { - case TPointerEvent::EButton1Down: - *type = QEvent::MouseButtonPress; - *button = Qt::LeftButton; - break; - case TPointerEvent::EButton1Up: - *type = QEvent::MouseButtonRelease; - *button = Qt::LeftButton; - break; - case TPointerEvent::EButton2Down: - *type = QEvent::MouseButtonPress; - *button = Qt::MidButton; - break; - case TPointerEvent::EButton2Up: - *type = QEvent::MouseButtonRelease; - *button = Qt::MidButton; - break; - case TPointerEvent::EButton3Down: - *type = QEvent::MouseButtonPress; - *button = Qt::RightButton; - break; - case TPointerEvent::EButton3Up: - *type = QEvent::MouseButtonRelease; - *button = Qt::RightButton; - break; - case TPointerEvent::EDrag: - *type = QEvent::MouseMove; - *button = Qt::NoButton; - break; - case TPointerEvent::EMove: - // Qt makes no distinction between move and drag - *type = QEvent::MouseMove; - *button = Qt::NoButton; - break; - default: - *type = QEvent::None; - *button = Qt::NoButton; - break; - } - if (pEvent->iModifiers & EModifierDoubleClick){ - *type = QEvent::MouseButtonDblClick; - } - - if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick) - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button); - else if (*type == QEvent::MouseButtonRelease) - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button)); - - QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask; -} - -//### Can be replaced with CAknLongTapDetector if animation is required. -//NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,. -//also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used. -class QLongTapTimer : public CTimer -{ -public: - static QLongTapTimer* NewL(QAbstractLongTapObserver *observer); - QLongTapTimer(QAbstractLongTapObserver *observer); - void ConstructL(); -public: - void PointerEventL(const TPointerEvent &event); - void RunL(); -protected: -private: - QAbstractLongTapObserver *m_observer; - TPointerEvent m_event; - QPoint m_pressedCoordinates; - int m_dragDistance; -}; - -QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer) -{ - QLongTapTimer* self = new QLongTapTimer(observer); - self->ConstructL(); - return self; -} -void QLongTapTimer::ConstructL() -{ - CTimer::ConstructL(); -} - -QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh) -{ - m_observer = observer; - m_dragDistance = qApp->startDragDistance(); - CActiveScheduler::Add(this); -} - -void QLongTapTimer::PointerEventL(const TPointerEvent& event) -{ - if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat) - { - QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates); - if (diff.manhattanLength() < m_dragDistance) - return; - } - Cancel(); - m_event = event; - if (event.iType == TPointerEvent::EButton1Down) - { - m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY); - // must be same as KLongTapDelay in aknlongtapdetector.h - After(800000); - } -} -void QLongTapTimer::RunL() -{ - if (m_observer) - m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition); -} - -QSymbianControl::QSymbianControl(QWidget *w) - : CCoeControl() - , qwidget(w) - , m_longTapDetector(0) - , m_ignoreFocusChanged(0) - , m_symbianPopupIsOpen(0) - , m_inExternalScreenOverride(false) - , m_lastStatusPaneVisibility(0) -{ -} - -void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) -{ - if (!desktop) - { - if (isWindowOwning || !qwidget->parentWidget() - || qwidget->parentWidget()->windowType() == Qt::Desktop) { - RWindowGroup &wg(S60->windowGroup(qwidget)); - CreateWindowL(wg); - } else { - /** - * TODO: in order to avoid creating windows for all ancestors of - * this widget up to the root window, the parameter passed to - * CreateWindowL should be - * qwidget->parentWidget()->effectiveWinId(). However, if we do - * this, then we need to take care of re-parenting when a window - * is created for a widget between this one and the root window. - */ - CreateWindowL(qwidget->parentWidget()->winId()); - } - - // Necessary in order to be able to track the activation status of - // the control's window - qwidget->d_func()->createExtra(); - - SetFocusing(true); - m_longTapDetector = QLongTapTimer::NewL(this); - m_doubleClickTimer.invalidate(); - - DrawableWindow()->SetPointerGrab(ETrue); - } - -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS - if (OwnsWindow()) { - TTfxWindowPurpose windowPurpose(ETfxPurposeNone); - switch (qwidget->windowType()) { - case Qt::Dialog: - windowPurpose = ETfxPurposeDialogWindow; - break; - case Qt::Popup: - windowPurpose = ETfxPurposePopupWindow; - break; - case Qt::Tool: - windowPurpose = ETfxPurposeToolWindow; - break; - case Qt::ToolTip: - windowPurpose = ETfxPurposeToolTipWindow; - break; - case Qt::SplashScreen: - windowPurpose = ETfxPurposeSplashScreenWindow; - break; - default: - windowPurpose = (isWindowOwning || !qwidget->parentWidget() || qwidget->parentWidget()->windowType() == Qt::Desktop) - ? ETfxPurposeWindow : ETfxPurposeChildWindow; - break; - } - Window().SetPurpose(windowPurpose); - } -#endif -} - -QSymbianControl::~QSymbianControl() -{ - // Ensure backing store is deleted before the top-level - // window is destroyed - qt_widget_private(qwidget)->topData()->backingStore.destroy(); - - if (S60->curWin == this) - S60->curWin = 0; - if (!QApplicationPrivate::is_app_closing) { - QT_TRY { - setFocusSafely(false); - } QT_CATCH(const std::exception&) { - // ignore exceptions, nothing can be done - } - } - S60->appUi()->RemoveFromStack(this); - delete m_longTapDetector; -} - -void QSymbianControl::setWidget(QWidget *w) -{ - qwidget = w; -} - -QPoint QSymbianControl::translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const -{ - QPoint pos(pointerEventPos.iX, pointerEventPos.iY); - if (qwidget->d_func()->fixNativeOrientationCalled) { - QSize wsize = qwidget->size(); - TSize size = Size(); - if (size.iWidth == wsize.height() && size.iHeight == wsize.width()) { - qreal x = pos.x(); - qreal y = pos.y(); - pos.setX(size.iHeight - y); - pos.setY(x); - } - } - return pos; -} - -TRect QSymbianControl::translateRectForFixedNativeOrientation(const TRect &controlRect) const -{ - TRect rect = controlRect; - if (qwidget->d_func()->fixNativeOrientationCalled) { - QPoint a = translatePointForFixedNativeOrientation(rect.iTl); - QPoint b = translatePointForFixedNativeOrientation(rect.iBr); - if (a.x() < b.x()) { - rect.iTl.iX = a.x(); - rect.iBr.iX = b.x(); - } else { - rect.iTl.iX = b.x(); - rect.iBr.iX = a.x(); - } - if (a.y() < b.y()) { - rect.iTl.iY = a.y(); - rect.iBr.iY = b.y(); - } else { - rect.iTl.iY = b.y(); - rect.iBr.iY = a.y(); - } - } - return rect; -} - -void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ) -{ - QWidget *alienWidget; - QPoint widgetPos = translatePointForFixedNativeOrientation(aPenEventLocation); - QPoint globalPos = translatePointForFixedNativeOrientation(aPenEventScreenLocation); - alienWidget = qwidget->childAt(widgetPos); - if (!alienWidget) - alienWidget = qwidget; - -#if !defined(QT_NO_CONTEXTMENU) - QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse, widgetPos, globalPos, Qt::NoModifier); - qt_sendSpontaneousEvent(alienWidget, &contextMenuEvent); -#endif -} - -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER -void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event) -{ - QApplicationPrivate *d = QApplicationPrivate::instance(); - QPointF screenPos = qwidget->mapToGlobal(translatePointForFixedNativeOrientation(event->iPosition)); - qreal pressure; - if(d->pressureSupported - && event->Pressure() > 0) //workaround for misconfigured HAL - pressure = event->Pressure() / qreal(d->maxTouchPressure); - else - pressure = qreal(1.0); - processTouchEvent(event->PointerNumber(), event->iType, screenPos, pressure); -} -#endif - -void QSymbianControl::processTouchEvent(int pointerNumber, TPointerEvent::TType type, QPointF screenPos, qreal pressure) -{ - QRect screenGeometry = qApp->desktop()->screenGeometry(qwidget); - - QApplicationPrivate *d = QApplicationPrivate::instance(); - - QList<QTouchEvent::TouchPoint> points = d->appAllTouchPoints; - while (points.count() <= pointerNumber) - points.append(QTouchEvent::TouchPoint(points.count())); - - Qt::TouchPointStates allStates = 0; - for (int i = 0; i < points.count(); ++i) { - QTouchEvent::TouchPoint &touchPoint = points[i]; - - if (touchPoint.id() == pointerNumber) { - Qt::TouchPointStates state; - switch (type) { - case TPointerEvent::EButton1Down: -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - case TPointerEvent::EEnterHighPressure: -#endif - state = Qt::TouchPointPressed; - break; - case TPointerEvent::EButton1Up: -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - case TPointerEvent::EExitCloseProximity: -#endif - state = Qt::TouchPointReleased; - break; - case TPointerEvent::EDrag: - state = Qt::TouchPointMoved; - break; - default: - // how likely is this to happen? - state = Qt::TouchPointStationary; - break; - } - if (pointerNumber == 0) - state |= Qt::TouchPointPrimary; - touchPoint.setState(state); - - touchPoint.setScreenPos(screenPos); - touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(), - screenPos.y() / screenGeometry.height())); - - touchPoint.setPressure(pressure); - } else if (touchPoint.state() != Qt::TouchPointReleased) { - // all other active touch points should be marked as stationary - touchPoint.setState(Qt::TouchPointStationary); - } - - allStates |= touchPoint.state(); - } - - if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) { - // all touch points released - d->appAllTouchPoints.clear(); - } else { - d->appAllTouchPoints = points; - } - - QApplicationPrivate::translateRawTouchEvent(qwidget, - QTouchEvent::TouchScreen, - points); -} - -void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) -{ -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - if (pEvent.IsAdvancedPointerEvent()) { - const TAdvancedPointerEvent *advancedPointerEvent = pEvent.AdvancedPointerEvent(); - translateAdvancedPointerEvent(advancedPointerEvent); - if (advancedPointerEvent->PointerNumber() != 0) { - // only send mouse events for the first touch point - return; - } - } -#endif - - m_longTapDetector->PointerEventL(pEvent); - QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); -} - -void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) -{ - QMouseEvent::Type type; - Qt::MouseButton button; - mapS60MouseEventTypeToQt(&type, &button, &pEvent); - Qt::KeyboardModifiers modifiers = mapToQtModifiers(pEvent.iModifiers); - - QPoint widgetPos = translatePointForFixedNativeOrientation(pEvent.iPosition); - TPoint controlScreenPos = PositionRelativeToScreen(); - QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos; - S60->lastCursorPos = globalPos; - S60->lastPointerEventPos = widgetPos; - - QWidget *mouseGrabber = QWidget::mouseGrabber(); - - QWidget *popupWidget = qApp->activePopupWidget(); - QWidget *popupReceiver = 0; - if (popupWidget) { - QWidget *popupChild = popupWidget->childAt(popupWidget->mapFromGlobal(globalPos)); - popupReceiver = popupChild ? popupChild : popupWidget; - } - - if (mouseGrabber) { - if (popupReceiver) { - sendMouseEvent(popupReceiver, type, globalPos, button, modifiers); - } else { - sendMouseEvent(mouseGrabber, type, globalPos, button, modifiers); - } - // No Enter/Leave events in grabbing mode. - return; - } - - QWidget *widgetUnderPointer = qwidget->childAt(widgetPos); - if (!widgetUnderPointer) - widgetUnderPointer = qwidget; - - QApplicationPrivate::dispatchEnterLeave(widgetUnderPointer, S60->lastPointerEventTarget); - S60->lastPointerEventTarget = widgetUnderPointer; - - QWidget *receiver; - if (!popupReceiver && S60->mousePressTarget && type != QEvent::MouseButtonPress) { - receiver = S60->mousePressTarget; - if (type == QEvent::MouseButtonRelease) - S60->mousePressTarget = 0; - } else { - receiver = popupReceiver ? popupReceiver : widgetUnderPointer; - if (type == QEvent::MouseButtonPress) - S60->mousePressTarget = receiver; - } - -#if !defined(QT_NO_CURSOR) && !defined(Q_SYMBIAN_FIXED_POINTER_CURSORS) - if (S60->brokenPointerCursors) - qt_symbian_move_cursor_sprite(); -#endif - -//Generate single touch event for S60 5.0 (has touchscreen, does not have advanced pointers) -#ifndef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - if (S60->hasTouchscreen) { - processTouchEvent(0, pEvent.iType, QPointF(globalPos), 1.0); - } -#endif - - sendMouseEvent(receiver, type, globalPos, button, modifiers); -} - -#ifdef Q_WS_S60 -void QSymbianControl::HandleStatusPaneSizeChange() -{ - QS60MainAppUi *s60AppUi = static_cast<QS60MainAppUi *>(S60->appUi()); - s60AppUi->HandleStatusPaneSizeChange(); -} -#endif - -void QSymbianControl::sendMouseEvent( - QWidget *receiver, - QEvent::Type type, - const QPoint &globalPos, - Qt::MouseButton button, - Qt::KeyboardModifiers modifiers) -{ - Q_ASSERT(receiver); - QMouseEvent mEvent(type, receiver->mapFromGlobal(globalPos), globalPos, - button, QApplicationPrivate::mouse_buttons, modifiers); - QEventDispatcherS60 *dispatcher; - // It is theoretically possible for someone to install a different event dispatcher. - if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(receiver->d_func()->threadData->eventDispatcher)) != 0) { - if (dispatcher->excludeUserInputEvents()) { - dispatcher->saveInputEvent(this, receiver, new QMouseEvent(mEvent)); - return; - } - } - - sendMouseEvent(receiver, &mEvent); -} - -bool QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent) -{ - return qt_sendSpontaneousEvent(widget, mEvent); -} - -TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type) -{ - TKeyResponse r = EKeyWasNotConsumed; - QT_TRYCATCH_LEAVING(r = OfferKeyEvent(keyEvent, type)); - return r; -} - -TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type) -{ - /* - S60 has a confusing way of delivering key events. There are three types of - events: EEventKey, EEventKeyDown and EEventKeyUp. When a key is pressed, - EEventKeyDown is first generated, followed by EEventKey. Then, when the key is - released, EEventKeyUp is generated. - However, it is possible that only the EEventKey is generated alone, typically - in relation to virtual keyboards. In that case we need to take care to - generate both press and release events in Qt, since applications expect that. - We do this by having three states for each used scan code, depending on the - events received. See the switch below for what happens in each state - transition. - */ - - if (type != EEventKeyDown) - if (handleVirtualMouse(keyEvent, type) == EKeyWasConsumed) - return EKeyWasConsumed; - - TKeyResponse ret = EKeyWasNotConsumed; -#define GET_RETURN(x) (ret = ((x) == EKeyWasConsumed) ? EKeyWasConsumed : ret) - - // This top level switch corresponds to the states, and the inner switches - // correspond to the transitions. - QS60Data::ScanCodeState &scanCodeState = S60->scanCodeStates[keyEvent.iScanCode]; - switch (scanCodeState) { - case QS60Data::Unpressed: - switch (type) { - case EEventKeyDown: - scanCodeState = QS60Data::KeyDown; - break; - case EEventKey: - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); - break; - case EEventKeyUp: - // No action. - break; - } - break; - case QS60Data::KeyDown: - switch (type) { - case EEventKeyDown: - // This should never happen, just stay in this state to be safe. - break; - case EEventKey: - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); - scanCodeState = QS60Data::KeyDownAndKey; - break; - case EEventKeyUp: - scanCodeState = QS60Data::Unpressed; - break; - } - break; - case QS60Data::KeyDownAndKey: - switch (type) { - case EEventKeyDown: - // This should never happen, just stay in this state to be safe. - break; - case EEventKey: - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyPress)); - break; - case EEventKeyUp: - GET_RETURN(sendSymbianKeyEvent(keyEvent, QEvent::KeyRelease)); - scanCodeState = QS60Data::Unpressed; - break; - } - break; - } - return ret; - -#undef GET_RETURN -} - -TKeyResponse QSymbianControl::sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type) -{ - // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp - // events, we need to cache the keysyms from the EKeyEvent events. This is what - // resolveS60ScanCode does. - TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, - keyEvent.iCode); - int keyCode; - if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used - keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); - } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { - // Normal characters keys. - keyCode = s60Keysym; - } else { - // Special S60 keys. - keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym); - } - - Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); - QKeyEventEx qKeyEvent(type, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), - (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers); - QWidget *widget; - widget = QWidget::keyboardGrabber(); - if (!widget) { - if (QApplicationPrivate::popupWidgets != 0) { - widget = QApplication::activePopupWidget()->focusWidget(); - if (!widget) { - widget = QApplication::activePopupWidget(); - } - } else { - widget = QApplicationPrivate::focus_widget; - if (!widget) { - widget = qwidget; - } - } - } - - QEventDispatcherS60 *dispatcher; - // It is theoretically possible for someone to install a different event dispatcher. - if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) { - if (dispatcher->excludeUserInputEvents()) { - dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent)); - return EKeyWasConsumed; - } - } - return sendKeyEvent(widget, &qKeyEvent); -} - -TKeyResponse QSymbianControl::handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type) -{ -#ifndef QT_NO_CURSOR - if (S60->mouseInteractionEnabled && S60->virtualMouseRequired) { - //translate keys to pointer - if ((keyEvent.iScanCode >= EStdKeyLeftArrow && keyEvent.iScanCode <= EStdKeyDownArrow) || - (keyEvent.iScanCode >= EStdKeyDevice10 && keyEvent.iScanCode <= EStdKeyDevice13) || - keyEvent.iScanCode == EStdKeyDevice3) { - QPoint pos = QCursor::pos(); - TPointerEvent fakeEvent; - fakeEvent.iType = (TPointerEvent::TType)(-1); - fakeEvent.iModifiers = keyEvent.iModifiers; - TInt x = pos.x(); - TInt y = pos.y(); - if (type == EEventKeyUp) { - S60->virtualMouseAccelTimeout.start(); - switch (keyEvent.iScanCode) { - case EStdKeyLeftArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Left; - break; - case EStdKeyRightArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Right; - break; - case EStdKeyUpArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Up; - break; - case EStdKeyDownArrow: - S60->virtualMousePressedKeys &= ~QS60Data::Down; - break; - // diagonal keys (named aliases don't exist in 3.1 SDK) - case EStdKeyDevice10: - S60->virtualMousePressedKeys &= ~QS60Data::LeftUp; - break; - case EStdKeyDevice11: - S60->virtualMousePressedKeys &= ~QS60Data::RightUp; - break; - case EStdKeyDevice12: - S60->virtualMousePressedKeys &= ~QS60Data::RightDown; - break; - case EStdKeyDevice13: - S60->virtualMousePressedKeys &= ~QS60Data::LeftDown; - break; - case EStdKeyDevice3: //select - if (S60->virtualMousePressedKeys & QS60Data::Select) - fakeEvent.iType = TPointerEvent::EButton1Up; - S60->virtualMousePressedKeys &= ~QS60Data::Select; - break; - } - } - else if (type == EEventKey) { - int dx = 0; - int dy = 0; - if (keyEvent.iScanCode != EStdKeyDevice3) { - m_doubleClickTimer.invalidate(); - //reset mouse accelleration after a short time with no moves - const int maxTimeBetweenKeyEventsMs = 500; - if (S60->virtualMouseAccelTimeout.isValid() && - S60->virtualMouseAccelTimeout.hasExpired(maxTimeBetweenKeyEventsMs)) { - S60->virtualMouseAccelDX = 0; - S60->virtualMouseAccelDY = 0; - } - S60->virtualMouseAccelTimeout.invalidate(); - } - switch (keyEvent.iScanCode) { - case EStdKeyLeftArrow: - S60->virtualMousePressedKeys |= QS60Data::Left; - dx = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyRightArrow: - S60->virtualMousePressedKeys |= QS60Data::Right; - dx = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyUpArrow: - S60->virtualMousePressedKeys |= QS60Data::Up; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDownArrow: - S60->virtualMousePressedKeys |= QS60Data::Down; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice10: - S60->virtualMousePressedKeys |= QS60Data::LeftUp; - dx = -1; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice11: - S60->virtualMousePressedKeys |= QS60Data::RightUp; - dx = 1; - dy = -1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice12: - S60->virtualMousePressedKeys |= QS60Data::RightDown; - dx = 1; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice13: - S60->virtualMousePressedKeys |= QS60Data::LeftDown; - dx = -1; - dy = 1; - fakeEvent.iType = TPointerEvent::EMove; - break; - case EStdKeyDevice3: - // Platform bug. If you start pressing several keys simultaneously (for - // example for drag'n'drop), Symbian starts producing spurious up and - // down messages for some keys. Therefore, make sure we have a clean slate - // of pressed keys before starting a new button press. - if (S60->virtualMousePressedKeys & QS60Data::Select) { - return EKeyWasConsumed; - } else { - S60->virtualMousePressedKeys |= QS60Data::Select; - fakeEvent.iType = TPointerEvent::EButton1Down; - if (m_doubleClickTimer.isValid() - && !m_doubleClickTimer.hasExpired(QApplication::doubleClickInterval())) { - fakeEvent.iModifiers |= EModifierDoubleClick; - m_doubleClickTimer.invalidate(); - } else { - m_doubleClickTimer.start(); - } - } - break; - } - if (dx) { - int cdx = S60->virtualMouseAccelDX; - //reset accel on change of sign, else double accel - if (dx * cdx <= 0) - cdx = dx; - else - cdx *= 4; - //cap accelleration - if (dx * cdx > S60->virtualMouseMaxAccel) - cdx = dx * S60->virtualMouseMaxAccel; - //move mouse position - x += cdx; - S60->virtualMouseAccelDX = cdx; - } - - if (dy) { - int cdy = S60->virtualMouseAccelDY; - if (dy * cdy <= 0) - cdy = dy; - else - cdy *= 4; - if (dy * cdy > S60->virtualMouseMaxAccel) - cdy = dy * S60->virtualMouseMaxAccel; - y += cdy; - S60->virtualMouseAccelDY = cdy; - } - } - //clip to screen size (window server allows a sprite hotspot to be outside the screen) - int screenNumber = S60->screenNumberForWidget(qwidget); - if (x < 0) - x = 0; - else if (x >= S60->screenWidthInPixelsForScreen[screenNumber]) - x = S60->screenWidthInPixelsForScreen[screenNumber] - 1; - if (y < 0) - y = 0; - else if (y >= S60->screenHeightInPixelsForScreen[screenNumber]) - y = S60->screenHeightInPixelsForScreen[screenNumber] - 1; - TPoint epos(x, y); - TPoint cpos = epos - PositionRelativeToScreen(); - fakeEvent.iPosition = cpos; - fakeEvent.iParentPosition = epos; - if(fakeEvent.iType != -1) - HandlePointerEvent(fakeEvent); - return EKeyWasConsumed; - } - } -#endif - - return EKeyWasNotConsumed; -} - -void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent) -{ - switch (inputEvent->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: - sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent)); - break; - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent)); - break; - default: - // Shouldn't get here. - Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown"); - break; - } -} - -TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent) -{ -#if !defined(QT_NO_IM) && defined(Q_WS_S60) - if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) { - QInputContext *qic = widget->inputContext(); - if (qic && qic->filterEvent(keyEvent)) - return EKeyWasConsumed; - } -#endif // !defined(QT_NO_IM) && defined(Q_OS_SYMBIAN) - - if (widget && qt_sendSpontaneousEvent(widget, keyEvent)) - if (keyEvent->isAccepted()) - return EKeyWasConsumed; - - return EKeyWasNotConsumed; -} - -#if !defined(QT_NO_IM) && defined(Q_WS_S60) -TCoeInputCapabilities QSymbianControl::InputCapabilities() const -{ - QWidget *w = 0; - - if (qwidget->hasFocus()) - w = qwidget; - else - w = qwidget->focusWidget(); - - QCoeFepInputContext *ic; - if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled) - && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) { - return ic->inputCapabilities(); - } else { - return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0); - } -} -#endif - -void QSymbianControl::Draw(const TRect& controlRect) const -{ - // Set flag to avoid calling DrawNow in window surface - QWidget *window = qwidget->window(); - Q_ASSERT(window); - QTLWExtra *topExtra = window->d_func()->maybeTopData(); - Q_ASSERT(topExtra); - - TRect wcontrolRect = translateRectForFixedNativeOrientation(controlRect); - - if (!topExtra->inExpose) { - topExtra->inExpose = true; - if (!qwidget->isWindow()) { - // If we get here, then it means we have a native child window - // Since no content should ever be painted to these windows, we - // erase them with a transparent brush when they get an expose. - CWindowGc &gc = SystemGc(); - gc.SetBrushColor(TRgb(0, 0, 0, 0)); - gc.Clear(controlRect); - } - QRect exposeRect = qt_TRect2QRect(wcontrolRect); - qwidget->d_func()->syncBackingStore(exposeRect); - topExtra->inExpose = false; - } - - QWindowSurface *surface = qwidget->windowSurface(); - QPaintEngine *engine = surface ? surface->paintDevice()->paintEngine() : NULL; - - if (!engine) - return; - - const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents; - if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(wcontrolRect); - QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r)); - } - - // Map source rectangle into coordinates of the backing store. - const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY); - const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase); - const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size()); - - if (engine->type() == QPaintEngine::Raster) { - QS60WindowSurface *s60Surface; -#ifdef QT_GRAPHICSSYSTEM_RUNTIME - if (QApplicationPrivate::runtime_graphics_system) { - QRuntimeWindowSurface *rtSurface = - static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface()); - s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface.data()); - } else -#endif - s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface()); - - CFbsBitmap *bitmap = s60Surface->symbianBitmap(); - CWindowGc &gc = SystemGc(); - - QWExtra::NativePaintMode nativePaintMode = qwidget->d_func()->extraData()->nativePaintMode; - if(qwidget->d_func()->paintOnScreen()) - nativePaintMode = QWExtra::Disable; - - switch(nativePaintMode) { - case QWExtra::Disable: - // Do nothing - break; - case QWExtra::Blit: - case QWExtra::BlitWriteAlpha: - if (qwidget->d_func()->isOpaque || nativePaintMode == QWExtra::BlitWriteAlpha) - gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); - gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect); - break; - case QWExtra::ZeroFill: - if (Window().DisplayMode() == EColor16MA - || Window().DisplayMode() == Q_SYMBIAN_ECOLOR16MAP) { - gc.SetBrushStyle(CGraphicsContext::ESolidBrush); - gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); - gc.SetBrushColor(TRgb::Color16MA(0)); - gc.Clear(controlRect); - } else { - gc.SetBrushColor(TRgb(0x000000)); - gc.Clear(controlRect); - }; - break; - default: - Q_ASSERT(false); - } - } - - if (sendNativePaintEvents) { - const QRect r = qt_TRect2QRect(wcontrolRect); - // The draw ops aren't actually sent to WSERV until the graphics - // context is deactivated, which happens in the function calling - // this one. We therefore delay the delivery of endNativePaintEvent, - // to ensure that drawing has completed by the time the widget - // receives the event. Note that, if the widget needs to ensure - // that the draw ops have actually been executed into the output - // framebuffer, a call to RWsSession::Flush is required in the - // endNativePaintEvent implementation. - QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r)); - } -} - -void QSymbianControl::qwidgetResize_helper(const QSize &newSize) -{ - QRect cr = qwidget->geometry(); - QSize oldSize(cr.size()); - cr.setSize(newSize); - qwidget->data->crect = cr; - if (qwidget->isVisible()) { - QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData(); - bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = true; - QResizeEvent e(newSize, oldSize); - qt_sendSpontaneousEvent(qwidget, &e); - if (!qwidget->testAttribute(Qt::WA_StaticContents)) - qwidget->d_func()->syncBackingStore(); - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = false; - } else { - if (!qwidget->testAttribute(Qt::WA_PendingResizeEvent)) { - QResizeEvent *e = new QResizeEvent(newSize, oldSize); - QApplication::postEvent(qwidget, e); - } - } -} - -void QSymbianControl::SizeChanged() -{ - CCoeControl::SizeChanged(); - - // When FixNativeOrientation had been called, the RWindow/CCoeControl size - // and the surface/QWidget size have nothing to do with each other. - if (qwidget->d_func()->fixNativeOrientationCalled) - return; - - QSize oldSize = qwidget->size(); - QSize newSize(Size().iWidth, Size().iHeight); - - if (oldSize != newSize) { - // Enforce the proper size for fullscreen widgets on the secondary screen. - const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; - const int screenNumber = S60->screenNumberForWidget(qwidget); - if (!m_inExternalScreenOverride && isFullscreen && screenNumber > 0) { - int screenWidth = S60->screenWidthInPixelsForScreen[screenNumber]; - int screenHeight = S60->screenHeightInPixelsForScreen[screenNumber]; - TSize screenSize(screenWidth, screenHeight); - if (screenWidth > 0 && screenHeight > 0 && screenSize != Size()) { - m_inExternalScreenOverride = true; - SetExtent(TPoint(0, 0), screenSize); - return; - } - } - - qwidgetResize_helper(newSize); - } - - m_inExternalScreenOverride = false; - - // CCoeControl::SetExtent calls SizeChanged, but does not call - // PositionChanged, so we call it here to ensure that the widget's - // position is updated. - PositionChanged(); -} - -void QSymbianControl::PositionChanged() -{ - CCoeControl::PositionChanged(); - - QPoint oldPos = qwidget->geometry().topLeft(); - QPoint newPos(Position().iX, Position().iY); - - if (oldPos != newPos) { - QRect cr = qwidget->geometry(); - cr.moveTopLeft(newPos); - qwidget->data->crect = cr; - QTLWExtra *top = qwidget->d_func()->maybeTopData(); - if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState) - top->normalGeometry.moveTopLeft(newPos); - if (qwidget->isVisible()) { - QMoveEvent e(newPos, oldPos); - qt_sendSpontaneousEvent(qwidget, &e); - } else { - QMoveEvent * e = new QMoveEvent(newPos, oldPos); - QApplication::postEvent(qwidget, e); - } - } -} - -void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) -{ - if (m_ignoreFocusChanged || (qwidget->windowType() & Qt::WindowType_Mask) == Qt::Desktop) - return; - -#ifdef Q_WS_S60 - if (S60->splitViewLastWidget) - return; -#endif - - // Popups never get focused, but still receive the FocusChanged when they are hidden. - if (QApplicationPrivate::popupWidgets != 0 - || (qwidget->windowType() & Qt::Popup) == Qt::Popup) - return; - - if (IsFocused() && IsVisible()) { - if (m_symbianPopupIsOpen) { - QWidget *fw = QApplication::focusWidget(); - if (fw) { - QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); - QCoreApplication::sendEvent(fw, &event); - } - m_symbianPopupIsOpen = false; - } - - QApplication::setActiveWindow(qwidget->window()); - qwidget->d_func()->setWindowIcon_sys(true); - qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); -#ifdef Q_WS_S60 - if (qwidget->isWindow()) - S60->setRecursiveDecorationsVisibility(qwidget, qwidget->windowState()); -#endif - } else if (QApplication::activeWindow() == qwidget->window()) { - bool focusedControlFound = false; - WId winId = 0; - for (QWidget *w = qwidget->parentWidget(); w && (winId = w->internalWinId()); w = w->parentWidget()) { - if (winId->IsFocused() && winId->IsVisible()) { - focusedControlFound = true; - break; - } else if (w->isWindow()) - break; - } - if (!focusedControlFound) { - if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) { - QWidget *fw = QApplication::focusWidget(); - if (fw) { - QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); - QCoreApplication::sendEvent(fw, &event); - } - m_symbianPopupIsOpen = true; - return; - } - - QApplication::setActiveWindow(0); - } - } - // else { We don't touch the active window unless we were explicitly activated or deactivated } -} - -void QSymbianControl::handleClientAreaChange() -{ - const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; - if (qwidget->isFullScreen() && !cbaVisibilityHint) { - SetExtentToWholeScreen(); - } else if (qwidget->isMaximized() || (qwidget->isFullScreen() && cbaVisibilityHint)) { - TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); - SetExtent(r.iTl, r.Size()); - } else if (!qwidget->isMinimized()) { // Normal geometry - if (!qwidget->testAttribute(Qt::WA_Resized)) { - qwidget->adjustSize(); - qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize - } - if (!qwidget->testAttribute(Qt::WA_Moved) && qwidget->windowType() != Qt::Dialog) { - TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); - SetPosition(r.iTl); - qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position - } - } -} - -bool QSymbianControl::isSplitViewWidget(QWidget *widget) { - bool returnValue = true; - //Ignore events sent to non-active windows, not visible widgets and not parents of input widget. - if (!qwidget->isActiveWindow() - || !qwidget->isVisible() - || !qwidget->isAncestorOf(widget)) { - - returnValue = false; - } - return returnValue; -} - -void QSymbianControl::HandleResourceChange(int resourceType) -{ - switch (resourceType) { - case KSplitViewCloseEvent: //intentional fall-through - case KSplitViewOpenEvent: { -#if !defined(QT_NO_IM) && defined(Q_WS_S60) - - //Fetch widget getting the text input - QWidget *widget = QWidget::keyboardGrabber(); - if (!widget) { - if (QApplicationPrivate::popupWidgets) { - widget = QApplication::activePopupWidget()->focusWidget(); - if (!widget) { - widget = QApplication::activePopupWidget(); - } - } else { - widget = QApplicationPrivate::focus_widget; - if (!widget) { - widget = qwidget; - } - } - } - if (widget) { - QCoeFepInputContext *ic = qobject_cast<QCoeFepInputContext *>(widget->inputContext()); - if (!ic) { - ic = qobject_cast<QCoeFepInputContext *>(qApp->inputContext()); - } - if (ic && isSplitViewWidget(widget)) { - if (resourceType == KSplitViewCloseEvent) { - ic->resetSplitViewWidget(); - } else { - ic->ensureFocusWidgetVisible(widget); - } - } - } -#endif // !defined(QT_NO_IM) && defined(Q_WS_S60) - } - break; - case KInternalStatusPaneChange: - // When status pane is not visible, only handle client area change if status pane was - // previously visible, as size changes to hidden status pane should not affect - // client area. - if (S60->statusPane() && (S60->statusPane()->IsVisible() || m_lastStatusPaneVisibility)) { - m_lastStatusPaneVisibility = S60->statusPane()->IsVisible(); - handleClientAreaChange(); - } - if (IsFocused() && IsVisible()) { - qwidget->d_func()->setWindowIcon_sys(true); - qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); - } - break; - case KUidValueCoeFontChangeEvent: - // font change event - break; -#ifdef Q_WS_S60 - case KEikDynamicLayoutVariantSwitch: - { - handleClientAreaChange(); - // Send resize event to trigger desktopwidget workAreaResized signal - if (qt_desktopWidget) { - QResizeEvent e(qt_desktopWidget->size(), qt_desktopWidget->size()); - QApplication::sendEvent(qt_desktopWidget, &e); - } - break; - } -#endif - default: - break; - } - - CCoeControl::HandleResourceChange(resourceType); - -} -void QSymbianControl::CancelLongTapTimer() -{ - m_longTapDetector->Cancel(); -} - -TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) -{ - if (id.iUid == ETypeId) - return id.MakePtr(this); - - return CCoeControl::MopSupplyObject(id); -} - -void QSymbianControl::setFocusSafely(bool focus) -{ - // The stack hack in here is very unfortunate, but it is the only way to ensure proper - // focus in Symbian. If this is not executed, the control which happens to be on - // the top of the stack may randomly be assigned focus by Symbian, for example - // when creating new windows (specifically in CCoeAppUi::HandleStackChanged()). - - // Close any popups. - CEikonEnv::Static()->EikAppUi()->StopDisplayingMenuBar(); - - if (focus) { - S60->appUi()->RemoveFromStack(this); - // Symbian doesn't automatically remove focus from the last focused control, so we need to - // remember it and clear focus ourselves. - if (lastFocusedControl && lastFocusedControl != this) - lastFocusedControl->SetFocus(false); - QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, - ECoeStackPriorityDefault + 1, ECoeStackFlagStandard)); // Note the + 1 - lastFocusedControl = this; - this->SetFocus(true); - } else { - S60->appUi()->RemoveFromStack(this); - QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, - ECoeStackPriorityDefault, ECoeStackFlagStandard)); - if(this == lastFocusedControl) - lastFocusedControl = 0; - this->SetFocus(false); - } -} - -bool QSymbianControl::isControlActive() -{ - return IsActivated() ? true : false; -} - -void QSymbianControl::ensureFixNativeOrientation() -{ -#if defined(Q_SYMBIAN_SUPPORTS_FIXNATIVEORIENTATION) - if (!qwidget->isWindow() || qwidget->windowType() == Qt::Desktop) - return; - if (S60->screenNumberForWidget(qwidget) > 0) - return; - const bool isFixed = qwidget->d_func()->fixNativeOrientationCalled; - const bool isFixEnabled = qwidget->testAttribute(Qt::WA_SymbianNoSystemRotation); - const bool isFullScreen = qwidget->windowState().testFlag(Qt::WindowFullScreen); - if (isFullScreen && isFixEnabled) { - const bool surfaceBasedGs = - QApplicationPrivate::graphics_system_name == QLatin1String("openvg") - || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"); - if (!surfaceBasedGs) - qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); - if (!isFixed && surfaceBasedGs) { - if (Window().FixNativeOrientation() == KErrNone) { - qwidget->d_func()->fixNativeOrientationCalled = true; - // The EGL window surface is now fixed to the native orientation - // of the device, no matter what size we pass when creating it. - // Enforce the same size for the QWidget too. For the underlying - // CCoeControl and RWindow it is up to the system to resize them - // when the standard auto-rotation mechanism is in use, we must not - // change that behavior by forcing any size for those. In practice - // this means that the QWidget and the underlying native control - // dimensions will be out of sync when FixNativeOrientation was - // called and the device is turned to the non-native (typically - // landscape) orientation. The pointer event handling and certain - // functions like Draw() will need to compensate for this. - QSize newSize(S60->nativeScreenWidthInPixels, S60->nativeScreenHeightInPixels); - if (qwidget->size() != newSize) - qwidgetResize_helper(newSize); - } else { - qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); - } - } - } else if (isFixed) { - qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); - qwidget->d_func()->fixNativeOrientationCalled = false; - qwidget->hide(); - qwidget->d_func()->create_sys(0, false, true); - qwidget->show(); - } -#else - qwidget->setAttribute(Qt::WA_SymbianNoSystemRotation, false); -#endif -} - -/*! - \typedef QApplication::QS60MainApplicationFactory - \since 4.6 - - This is a typedef for a pointer to a function with the following - signature: - - \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 47 - - \sa QApplication::QApplication() -*/ - -/*! - \since 4.6 - - Creates an application using the application factory given in - \a factory, and using \a argc command line arguments in \a argv. - \a factory can be leaving, but the error will be converted to a - standard exception. - - This function is only available on S60. -*/ -QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) -{ - Q_D(QApplication); - S60->s60ApplicationFactory = factory; - d->construct(); -} - -QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) -{ - Q_D(QApplication); - S60->s60ApplicationFactory = factory; - d->construct(); - QApplicationPrivate::app_compile_version = _internal; -} - -void qt_init(QApplicationPrivate * /* priv */, int) -{ - if (!CCoeEnv::Static()) { - // The S60 framework creates a new trap handler which will render any existing traps - // invalid as long as it is active. This means that all code in main() that occurs after - // the QApplication construction needs to be surrounded by a new trap, despite having - // an outer one already. To avoid this, we save the original trap handler here, and set - // it back after the S60 framework is constructed. Then we restore it right before the S60 - // framework destruction. - TTrapHandler *origTrapHandler = User::TrapHandler(); - - // The S60 framework has not been initialized. We need to do it. - TApaApplicationFactory factory(S60->s60ApplicationFactory ? - S60->s60ApplicationFactory : newS60Application); - CApaCommandLine* commandLine = q_check_ptr(QCoreApplicationPrivate::symbianCommandLine()); - if (commandLine) { - // After this construction, CEikonEnv will be available from CEikonEnv::Static(). - // (much like our qApp). - QtEikonEnv* coe = new QtEikonEnv; - //not using QT_TRAP_THROWING, because coe owns the cleanupstack so it can't be pushed there. - TRAPD(err, coe->ConstructAppFromCommandLineL(factory, *commandLine)); - if(err != KErrNone) { - qWarning() << "qt_init: Eikon application construct failed (" - << err - << "), maybe missing resource file on S60 3.1?"; - delete coe; - qt_symbian_throwIfError(err); - } - } - - S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler); - - S60->qtOwnsS60Environment = true; - } else { - S60->qtOwnsS60Environment = false; - } - -#ifdef QT_NO_DEBUG - if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty()) -#endif - S60->wsSession().SetAutoFlush(ETrue); - -#ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE - TRAP_IGNORE(S60->wsSession().EnableWindowSizeCacheL()); -#endif - - S60->updateScreenSize(); - - - TDisplayMode mode = S60->screenDevice()->DisplayMode(); - S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode); - - //NB: RWsSession::GetColorModeList tells you what window modes are supported, - //not what bitmap formats. - if(QSysInfo::symbianVersion() == QSysInfo::SV_9_2) - S60->supportsPremultipliedAlpha = 0; - else - S60->supportsPremultipliedAlpha = 1; - - RProcess me; - TSecureId securId = me.SecureId(); - S60->uid = securId.operator TUid(); - - // enable focus events - used to re-enable mouse after focus changed between mouse and non mouse app, - // and for dimming behind modal windows - S60->windowGroup().EnableFocusChangeEvents(); - - //Check if mouse interaction is supported (either EMouse=1 in the HAL, or EMachineUID is one of the phones known to support this) - const TInt KMachineUidSamsungI8510 = 0x2000C51E; - // HAL::Get(HALData::EPen, TInt& result) may set 'result' to 1 on some 3.1 systems (e.g. N95). - // But we know that S60 systems below 5.0 did not support touch. - static const bool touchIsUnsupportedOnSystem = - QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 - || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2; - TInt machineUID; - TInt mouse; - TInt touch; - TInt err; - err = HAL::Get(HALData::EMouse, mouse); - if (err != KErrNone) - mouse = 0; - err = HAL::Get(HALData::EMachineUid, machineUID); - if (err != KErrNone) - machineUID = 0; - err = HAL::Get(HALData::EPen, touch); - if (err != KErrNone || touchIsUnsupportedOnSystem) - touch = 0; -#ifdef __WINS__ - if(QSysInfo::symbianVersion() <= QSysInfo::SV_9_4) { - //for symbian SDK emulator, force values to match typical devices. - mouse = 0; - touch = touchIsUnsupportedOnSystem ? 0 : 1; - } -#endif - if (mouse || machineUID == KMachineUidSamsungI8510) { - S60->hasTouchscreen = false; - S60->virtualMouseRequired = false; - } - else if (!touch) { - S60->hasTouchscreen = false; - S60->virtualMouseRequired = true; - } - else { - S60->hasTouchscreen = true; - S60->virtualMouseRequired = false; - } - - S60->avkonComponentsSupportTransparency = false; - S60->menuBeingConstructed = false; - -#ifdef Q_WS_S60 - TUid KCRUidAvkon = { 0x101F876E }; - TUint32 KAknAvkonTransparencyEnabled = 0x0000000D; - - CRepository* repository = 0; - TRAP(err, repository = CRepository::NewL(KCRUidAvkon)); - - if(err == KErrNone) { - TInt value = 0; - err = repository->Get(KAknAvkonTransparencyEnabled, value); - if(err == KErrNone) { - S60->avkonComponentsSupportTransparency = (value==1) ? true : false; - } - } - delete repository; - repository = 0; -#endif - - qt_keymapper_private()->updateInputLanguage(); - -#ifdef QT_KEYPAD_NAVIGATION - if (touch) { - QApplicationPrivate::navigationMode = Qt::NavigationModeNone; - } else { - QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; - } -#endif - -#ifndef QT_NO_CURSOR - //Check if window server pointer cursors are supported or not -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - //In generic binary, use the HAL and OS version - //Any other known good phones should be added here. - if (machineUID == KMachineUidSamsungI8510 || (QSysInfo::symbianVersion() != QSysInfo::SV_9_4 - && QSysInfo::symbianVersion() != QSysInfo::SV_9_3 && QSysInfo::symbianVersion() - != QSysInfo::SV_9_2)) { - S60->brokenPointerCursors = false; - qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup()); - } - else - S60->brokenPointerCursors = true; -#endif - - if (S60->mouseInteractionEnabled) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) { - qt_symbian_set_pointer_sprite(Qt::ArrowCursor); - qt_symbian_show_pointer_sprite(); - } - else -#endif - S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); - } -#endif - - QFont systemFont; - systemFont.setFamily(systemFont.defaultFamily()); - QApplicationPrivate::setSystemFont(systemFont); - - QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit())); - -#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - QApplicationPrivate::instance()->useTranslucentEGLSurfaces = true; - - const TUid KIvePropertyCat = {0x2726beef}; - enum TIvePropertyChipType { - EVCBCM2727B1 = 0x00000000, - EVCBCM2763A0 = 0x04000100, - EVCBCM2763B0 = 0x04000102, - EVCBCM2763C0 = 0x04000103, - EVCBCM2763C1 = 0x04000104, - EVCBCMUnknown = 0x7fffffff - }; - - TInt chipType = EVCBCMUnknown; - if (RProperty::Get(KIvePropertyCat, 0 /*chip type*/, chipType) == KErrNone) { - if (chipType == EVCBCM2727B1) { - // We have only 32MB GPU memory. Use raster surfaces - // for transparent TLWs. - QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; - } - } else { - QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; - } - if (QApplicationPrivate::graphics_system_name == QLatin1String("raster")) - QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; -#else - QApplicationPrivate::instance()->useTranslucentEGLSurfaces = false; -#endif -/* - ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag - int argc = priv->argc; - char **argv = priv->argv; - - // Get command line params - int j = argc ? 1 : 0; - for (int i=1; i<argc; i++) { - if (argv[i] && *argv[i] != '-') { - argv[j++] = argv[i]; - continue; - } - -#if defined(QT_DEBUG) - if (qstrcmp(argv[i], "-nograb") == 0) - appNoGrab = !appNoGrab; - else -#endif // QT_DEBUG - ; - } -*/ - - // Register WId with the metatype system. This is to enable - // QWidgetPrivate::create_sys to used delayed slot invocation in order - // to destroy WId objects during reparenting. - qRegisterMetaType<WId>("WId"); -} - -#ifdef QT_NO_FREETYPE -extern void qt_cleanup_symbianFontDatabase(); // qfontdatabase_s60.cpp -#endif - -/***************************************************************************** - qt_cleanup() - cleans up when the application is finished - *****************************************************************************/ -void qt_cleanup() -{ -#ifdef Q_WS_S60 - S60->setButtonGroupContainer(0); -#endif - if(qt_S60Beep) { - delete qt_S60Beep; - qt_S60Beep = 0; - } - QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles - QPixmapCache::clear(); // Has to happen now, since QS60PixmapData has FBS handles - -#ifdef QT_NO_FREETYPE - qt_cleanup_symbianFontDatabase(); -#endif -// S60 structure and window server session are freed in eventdispatcher destructor as they are needed there - - // It's important that this happens here, before the event dispatcher gets - // deleted, because the input context needs the event loop one last time before - // it dies. - delete QApplicationPrivate::inputContext; - QApplicationPrivate::inputContext = 0; - - //Change mouse pointer back - S60->wsSession().SetPointerCursorMode(EPointerCursorNone); - -#ifdef Q_WS_S60 - // Clear CBA - CEikonEnv::Static()->AppUiFactory()->SwapButtonGroup(0); - delete S60->buttonGroupContainer(); - S60->setButtonGroupContainer(0); -#endif - - // Call EndFullScreen() to prevent confusing the system effect state machine. - qt_endFullScreenEffect(); - - if (S60->qtOwnsS60Environment) { - // Restore the S60 framework trap handler. See qt_init(). - User::SetTrapHandler(S60->s60InstalledTrapHandler); - - CEikonEnv* coe = CEikonEnv::Static(); - coe->PrepareToExit(); - // The CEikonEnv itself is destroyed in here. - coe->DestroyEnvironment(); - } -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ - // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash() - // Possibly a task fot the S60Style guys -} - -void QApplicationPrivate::createEventDispatcher() -{ - Q_Q(QApplication); - eventDispatcher = new QEventDispatcherS60(q); -} - -QString QApplicationPrivate::appName() const -{ - return QCoreApplicationPrivate::appName(); -} - -bool QApplicationPrivate::modalState() -{ - return app_do_modal; -} - -void QApplicationPrivate::enterModal_sys(QWidget *widget) -{ -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS - S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter); -#endif - if (widget) { - static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue); - // Modal partial screen dialogs (like queries) capture pointer events. - // ### FixMe: Add specialized behaviour for fullscreen modal dialogs - widget->effectiveWinId()->SetGloballyCapturing(ETrue); - widget->effectiveWinId()->SetPointerCapture(ETrue); - } - if (!qt_modal_stack) - qt_modal_stack = new QWidgetList; - qt_modal_stack->insert(0, widget); - app_do_modal = true; -} - -void QApplicationPrivate::leaveModal_sys(QWidget *widget) -{ -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS - S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit); -#endif - if (widget) { - static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse); - // ### FixMe: Add specialized behaviour for fullscreen modal dialogs - widget->effectiveWinId()->SetGloballyCapturing(EFalse); - widget->effectiveWinId()->SetPointerCapture(EFalse); - } - if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { - if (qt_modal_stack->isEmpty()) { - delete qt_modal_stack; - qt_modal_stack = 0; - } - } - app_do_modal = qt_modal_stack != 0; -} - -void QApplicationPrivate::openPopup(QWidget *popup) -{ - if (popup && qobject_cast<QComboBox *>(popup->parentWidget())) - static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(ETrue); - - if (!QApplicationPrivate::popupWidgets) - QApplicationPrivate::popupWidgets = new QWidgetList; - QApplicationPrivate::popupWidgets->append(popup); - - // Cancel focus widget pointer capture and long tap timer - if (QApplication::focusWidget()) { - static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer(); - QApplication::focusWidget()->effectiveWinId()->SetPointerCapture(false); - } - - if (!qt_nograb()) { - // Cancel pointer capture and long tap timer for earlier popup - int popupCount = QApplicationPrivate::popupWidgets->count(); - if (popupCount > 1) { - QWidget* prevPopup = QApplicationPrivate::popupWidgets->at(popupCount-2); - static_cast<QSymbianControl*>(prevPopup->effectiveWinId())->CancelLongTapTimer(); - prevPopup->effectiveWinId()->SetPointerCapture(false); - } - - // Enable pointer capture for this (topmost) popup - Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); - WId id = popup->effectiveWinId(); - id->SetPointerCapture(true); - } - - // popups are not focus-handled by the window system (the first - // popup grabbed the keyboard), so we have to do that manually: A - // new popup gets the focus - QWidget *fw = popup->focusWidget(); - if (fw) { - fw->setFocus(Qt::PopupFocusReason); - } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup - fw = QApplication::focusWidget(); - if (fw) { - QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - q_func()->sendEvent(fw, &e); - } - } -} - -void QApplicationPrivate::closePopup(QWidget *popup) -{ - if (popup && qobject_cast<QComboBox *>(popup->parentWidget())) - static_cast<QSymbianControl *>(popup->effectiveWinId())->FadeBehindPopup(EFalse); - - if (!QApplicationPrivate::popupWidgets) - return; - QApplicationPrivate::popupWidgets->removeAll(popup); - - // Cancel pointer capture and long tap for this popup - WId id = popup->effectiveWinId(); - id->SetPointerCapture(false); - static_cast<QSymbianControl*>(id)->CancelLongTapTimer(); - - if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup - delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = 0; - if (!qt_nograb()) { // grabbing not disabled - Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); - if (QWidgetPrivate::mouseGrabber != 0) - QWidgetPrivate::mouseGrabber->grabMouse(); - - if (QWidgetPrivate::keyboardGrabber != 0) - QWidgetPrivate::keyboardGrabber->grabKeyboard(); - - QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget() - : q_func()->focusWidget(); - if (fw) { - if(fw->window()->isModal()) // restore pointer capture for modal window - fw->effectiveWinId()->SetPointerCapture(true); - - if (fw != q_func()->focusWidget()) { - fw->setFocus(Qt::PopupFocusReason); - } else { - QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); - q_func()->sendEvent(fw, &e); - } - } - } - } else { - - // popups are not focus-handled by the window system (the - // first popup grabbed the keyboard), so we have to do that - // manually: A popup was closed, so the previous popup gets - // the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->last(); - if (QWidget *fw = QApplication::focusWidget()) { - QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - q_func()->sendEvent(fw, &e); - } - - // Enable pointer capture for previous popup - if (aw) { - aw->effectiveWinId()->SetPointerCapture(true); - } - } -} - -QWidget * QApplication::topLevelAt(QPoint const& point) -{ - QWidget *found = 0; - int lowestZ = INT_MAX; - QWidgetList list = QApplication::topLevelWidgets(); - for (int i = 0; i < list.count(); ++i) { - QWidget *widget = list.at(i); - if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) { - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - if (widget->geometry().adjusted(0,0,1,1).contains(point)) { - // At this point we know there is a Qt widget under the point. - // Now we need to make sure it is the top most in the z-order. - RDrawableWindow *const window = widget->effectiveWinId()->DrawableWindow(); - int z = window->OrdinalPosition(); - if (z < lowestZ) { - lowestZ = z; - found = widget; - } - } - } - } - return found; -} - -void QApplication::alert(QWidget * /* widget */, int /* duration */) -{ - // TODO: Implement QApplication::alert(QWidget *widget, int duration) -} - -int QApplication::doubleClickInterval() -{ - TTimeIntervalMicroSeconds32 us; - TInt distance; - S60->wsSession().GetDoubleClickSettings(us, distance); - return (us.Int() / 1000); -} - -void QApplication::setDoubleClickInterval(int ms) -{ - TTimeIntervalMicroSeconds32 newUs( ms * 1000); - TTimeIntervalMicroSeconds32 us; - TInt distance; - S60->wsSession().GetDoubleClickSettings(us, distance); - if (us != newUs) - S60->wsSession().SetDoubleClick(newUs, distance); -} - -int QApplication::keyboardInputInterval() -{ - return QApplicationPrivate::keyboard_input_time; -} - -void QApplication::setKeyboardInputInterval(int ms) -{ - QApplicationPrivate::keyboard_input_time = ms; -} - -int QApplication::cursorFlashTime() -{ - return QApplicationPrivate::cursor_flash_time; -} - -void QApplication::setCursorFlashTime(int msecs) -{ - QApplicationPrivate::cursor_flash_time = msecs; -} - -void QApplication::beep() -{ - if (!qt_S60Beep) { - TInt frequency = 880; - TTimeIntervalMicroSeconds duration(500000); - TRAP_IGNORE(qt_S60Beep=QS60Beep::NewL(frequency, duration)); - } - if (qt_S60Beep) - qt_S60Beep->Play(); -} - -static inline bool callSymbianEventFilters(const QSymbianEvent *event) -{ - long unused; - return qApp->filterEvent(const_cast<QSymbianEvent *>(event), &unused); -} - -/*! - \warning This function is only available on Symbian. - \since 4.6 - - This function processes an individual Symbian event - \a event. It returns 1 if the event was handled, 0 if - the \a event was not handled, and -1 if the event was - not handled because the event is not known to Qt. - */ - -int QApplication::symbianProcessEvent(const QSymbianEvent *event) -{ - Q_D(QApplication); - - QScopedLoopLevelCounter counter(d->threadData); - - if (d->eventDispatcher->filterEvent(const_cast<QSymbianEvent *>(event))) - return 1; - - QWidget *w = qApp ? qApp->focusWidget() : 0; - if (w) { - QInputContext *ic = w->inputContext(); - if (ic && ic->symbianFilterEvent(w, event)) - return 1; - } - - if (symbianEventFilter(event)) - return 1; - - switch (event->type()) { - case QSymbianEvent::WindowServerEvent: - return d->symbianProcessWsEvent(event); - case QSymbianEvent::CommandEvent: - return d->symbianHandleCommand(event); - case QSymbianEvent::ResourceChangeEvent: - return d->symbianResourceChange(event); - default: - return -1; - } -} - -int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent) -{ - // Qt event handling. Handle some events regardless of if the handle is in our - // widget map or not. - const TWsEvent *event = symbianEvent->windowServerEvent(); - CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle()); - const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control); - switch (event->Type()) { - case EEventPointerEnter: - if (controlInMap) { - callSymbianEventFilters(symbianEvent); - return 1; // Qt::Enter will be generated in HandlePointerL - } - break; - case EEventPointerExit: - if (controlInMap) { - if (callSymbianEventFilters(symbianEvent)) - return 1; - if (S60) { - // mouseEvent outside our window, send leave event to last focused widget - QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos, - Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier); - if (S60->lastPointerEventTarget) - qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent); - S60->lastPointerEventTarget = 0; - } - return 1; - } - break; - case EEventScreenDeviceChanged: // fallthrough -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - case EEventDisplayChanged: -#endif - if (callSymbianEventFilters(symbianEvent)) - return 1; - if (S60) - S60->updateScreenSize(); - if (qt_desktopWidget) { - QSize oldSize = qt_desktopWidget->size(); - qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels); - qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels); - QResizeEvent e(qt_desktopWidget->size(), oldSize); - QApplication::sendEvent(qt_desktopWidget, &e); - } - return 0; // Propagate to CONE - case EEventWindowVisibilityChanged: - if (controlInMap) { - if (callSymbianEventFilters(symbianEvent)) - return 1; - const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged(); - if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) - S60->controlVisibilityChanged(control, false); - else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) - S60->controlVisibilityChanged(control, true); - return 1; - } - break; - case EEventFocusGained: - if (callSymbianEventFilters(symbianEvent)) - return 1; -#ifndef QT_NO_CURSOR - //re-enable mouse interaction - if (S60->mouseInteractionEnabled) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_show_pointer_sprite(); - else -#endif - S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); - } -#endif -#ifdef QT_SOFTKEYS_ENABLED - if (!CEikonEnv::Static()->EikAppUi()->IsDisplayingMenuOrDialog()) - QSoftKeyManager::updateSoftKeys(); -#endif - break; - case EEventFocusLost: - if (callSymbianEventFilters(symbianEvent)) - return 1; -#ifndef QT_NO_CURSOR - //disable mouse as may be moving to application that does not support it - if (S60->mouseInteractionEnabled) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_hide_pointer_sprite(); - else -#endif - S60->wsSession().SetPointerCursorMode(EPointerCursorNone); - } -#endif - break; - case KGoomMemoryLowEvent: -#ifdef QT_DEBUG - qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryLowEvent"; -#endif - if (callSymbianEventFilters(symbianEvent)) - return 1; -#ifdef QT_GRAPHICSSYSTEM_RUNTIME - if(QApplicationPrivate::runtime_graphics_system) { - bool switchToSwRendering(false); - - foreach (QWidget *w, QApplication::topLevelWidgets()) { - if(w->d_func()->topData()->backingStore) { - switchToSwRendering = true; - break; - } - } - - if (switchToSwRendering) { - QRuntimeGraphicsSystem *gs = - static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system); - gs->setGraphicsSystem(QLatin1String("raster")); - } - } -#endif - break; - case KGoomMemoryGoodEvent: -#ifdef QT_DEBUG - qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryGoodEvent"; -#endif - if (callSymbianEventFilters(symbianEvent)) - return 1; -#ifdef QT_GRAPHICSSYSTEM_RUNTIME - if(QApplicationPrivate::runtime_graphics_system) { - QRuntimeGraphicsSystem *gs = - static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system); - gs->setGraphicsSystem(QLatin1String("openvg")); - } -#endif - break; -#ifdef Q_SYMBIAN_SUPPORTS_SURFACES - case EEventUser: - { - // GOOM is looking for candidates to kill so indicate that we are - // capable of cleaning up by handling this event - TInt32 *data = reinterpret_cast<TInt32 *>(event->EventData()); - if (data[0] == EApaSystemEventShutdown && data[1] == KGoomMemoryLowEvent) - return 1; - } - break; -#endif - -#ifdef Q_WS_S60 - case KEikInputLanguageChange: - qt_keymapper_private()->updateInputLanguage(); - break; -#endif - - default: - break; - } - - if (!controlInMap) - return -1; - - return 0; -} - -/*! - \warning This virtual function is only available on Symbian. - \since 4.6 - - If you create an application that inherits QApplication and reimplement - this function, you get direct access to events that the are received - from Symbian. The events are passed in the \a event parameter. - - Return true if you want to stop the event from being processed. Return - false for normal event dispatching. The default implementation returns - false, and does nothing with \a event. - */ -bool QApplication::symbianEventFilter(const QSymbianEvent *event) -{ - Q_UNUSED(event); - return false; -} - -/*! - \warning This function is only available on Symbian. - \since 4.6 - - Handles \a{command}s which are typically handled by - CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is - partially achieved by deriving from CAknAppUi. Currently, exit, - menu and softkey commands are handled. - - \sa s60EventFilter(), s60ProcessEvent() -*/ -int QApplicationPrivate::symbianHandleCommand(const QSymbianEvent *symbianEvent) -{ - Q_Q(QApplication); - int ret = 0; - - if (callSymbianEventFilters(symbianEvent)) - return 1; - - int command = symbianEvent->command(); - - switch (command) { -#ifdef Q_WS_S60 - case EAknSoftkeyExit: { - QCloseEvent ev; - QApplication::sendSpontaneousEvent(q, &ev); - if (ev.isAccepted()) { - q->quit(); - ret = 1; - } - break; - } -#endif - case EEikCmdExit: - q->quit(); - ret = 1; - break; - default: -#ifdef Q_WS_S60 - bool handled = QSoftKeyManager::handleCommand(command); - if (handled) - ret = 1; - else - ret = QMenuBarPrivate::symbianCommands(command); -#endif - break; - } - - return ret; -} - -/*! - \warning This function is only available on Symbian. - \since 4.6 - - Handles the resource change specified by \a type. - - Currently, KEikDynamicLayoutVariantSwitch and - KAknsMessageSkinChange are handled. - */ -int QApplicationPrivate::symbianResourceChange(const QSymbianEvent *symbianEvent) -{ - int ret = 0; - - int type = symbianEvent->resourceChangeType(); - - switch (type) { -#ifdef Q_WS_S60 - case KEikDynamicLayoutVariantSwitch: - { - if (callSymbianEventFilters(symbianEvent)) - return 1; - if (S60) - S60->updateScreenSize(); - -#ifndef QT_NO_STYLE_S60 - QS60Style *s60Style = 0; - -#ifndef QT_NO_STYLE_STYLESHEET - QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style()); - if (proxy) - s60Style = qobject_cast<QS60Style*>(proxy->baseStyle()); - else -#endif - s60Style = qobject_cast<QS60Style*>(QApplication::style()); - - if (s60Style) { - s60Style->d_func()->handleDynamicLayoutVariantSwitch(); - ret = 1; - } -#endif - } - break; - -#ifndef QT_NO_STYLE_S60 - case KAknsMessageSkinChange: - if (callSymbianEventFilters(symbianEvent)) - return 1; - if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style())) { - s60Style->d_func()->handleSkinChange(); - ret = 1; - } - break; -#endif -#endif // Q_WS_S60 - default: - break; - } - - return ret; -} - -#ifndef QT_NO_WHEELEVENT -int QApplication::wheelScrollLines() -{ - return QApplicationPrivate::wheel_scroll_lines; -} - -void QApplication::setWheelScrollLines(int n) -{ - QApplicationPrivate::wheel_scroll_lines = n; -} -#endif //QT_NO_WHEELEVENT - -bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */) -{ - // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect) - return false; -} - -void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */) -{ - // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) -} - -TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym) -{ - if (!scanCode) - return keysym; - - QApplicationPrivate *d = QApplicationPrivate::instance(); - - if (keysym) { - // If keysym is specified, cache it. - d->scanCodeCache.insert(scanCode, keysym); - return keysym; - } else { - // If not, retrieve the cached version. - return d->scanCodeCache[scanCode]; - } -} - -void QApplicationPrivate::initializeMultitouch_sys() -{ -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - if (HAL::Get(HALData::EPointer3DPressureSupported, pressureSupported) != KErrNone) - pressureSupported = 0; - if (HAL::Get(HALData::EPointer3DMaxPressure, maxTouchPressure) != KErrNone) - maxTouchPressure = KMaxTInt; -#else - pressureSupported = 0; - maxTouchPressure = KMaxTInt; -#endif -} - -void QApplicationPrivate::cleanupMultitouch_sys() -{ } - -#ifndef QT_NO_SESSIONMANAGER -QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */) -{ - -} - -QSessionManager::~QSessionManager() -{ - -} - -bool QSessionManager::allowsInteraction() -{ - return false; -} - -void QSessionManager::cancel() -{ - -} -#endif //QT_NO_SESSIONMANAGER - -#ifdef QT_KEYPAD_NAVIGATION -/* - * Show/Hide the mouse cursor depending on phone type and chosen mode - */ -void QApplicationPrivate::setNavigationMode(Qt::NavigationMode mode) -{ -#ifndef QT_NO_CURSOR - const bool wasCursorOn = (QApplicationPrivate::navigationMode == Qt::NavigationModeCursorAuto - && !S60->hasTouchscreen) - || QApplicationPrivate::navigationMode == Qt::NavigationModeCursorForceVisible; - const bool isCursorOn = (mode == Qt::NavigationModeCursorAuto - && !S60->hasTouchscreen) - || mode == Qt::NavigationModeCursorForceVisible; - - if (!wasCursorOn && isCursorOn) { - //Show the cursor, when changing from another mode to cursor mode - qt_symbian_set_cursor_visible(true); - } - else if (wasCursorOn && !isCursorOn) { - //Hide the cursor, when leaving cursor mode - qt_symbian_set_cursor_visible(false); - } -#endif - QApplicationPrivate::navigationMode = mode; -} -#endif - -#ifndef QT_NO_CURSOR -/***************************************************************************** - QApplication cursor stack - *****************************************************************************/ - -void QApplication::setOverrideCursor(const QCursor &cursor) -{ - qApp->d_func()->cursor_list.prepend(cursor); - qt_symbian_setGlobalCursor(cursor); -} - -void QApplication::restoreOverrideCursor() -{ - if (qApp->d_func()->cursor_list.isEmpty()) - return; - qApp->d_func()->cursor_list.removeFirst(); - - if (!qApp->d_func()->cursor_list.isEmpty()) { - qt_symbian_setGlobalCursor(qApp->d_func()->cursor_list.first()); - } - else { - //determine which widget has focus - QWidget *w = QApplication::widgetAt(QCursor::pos()); -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) { - qt_symbian_set_pointer_sprite(w ? w->cursor() : Qt::ArrowCursor); - } - else -#endif - { - //because of the internals of window server, we need to force the cursor - //to be set in all child windows too, otherwise when the cursor is over - //the child window it may show a widget cursor or arrow cursor instead, - //depending on construction order. - QListIterator<WId> iter(QWidgetPrivate::mapper->uniqueKeys()); - while (iter.hasNext()) { - CCoeControl *ctrl = iter.next(); - if(ctrl->OwnsWindow()) { - ctrl->DrawableWindow()->ClearPointerCursor(); - } - } - if (w) - qt_symbian_setWindowCursor(w->cursor(), w->effectiveWinId()); - else - qt_symbian_setWindowGroupCursor(Qt::ArrowCursor, S60->windowGroup()); - } - } -} - -#endif // QT_NO_CURSOR - -void QApplicationPrivate::_q_aboutToQuit() -{ - qt_beginFullScreenEffect(); - -#ifdef Q_SYMBIAN_TRANSITION_EFFECTS - // Send the shutdown tfx command - S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown); -#endif -} - -QS60ThreadLocalData::QS60ThreadLocalData() -{ - CCoeEnv *env = CCoeEnv::Static(); - if (env) { - //if this is the UI thread, share objects owned by CONE - usingCONEinstances = true; - wsSession = env->WsSession(); - screenDevice = env->ScreenDevice(); - } - else { - usingCONEinstances = false; - qt_symbian_throwIfError(wsSession.Connect(qt_s60GetRFs())); - screenDevice = new CWsScreenDevice(wsSession); - screenDevice->Construct(); - } -} - -QS60ThreadLocalData::~QS60ThreadLocalData() -{ - if (!usingCONEinstances) { - delete screenDevice; - wsSession.Close(); - } -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qclipboard_s60.cpp b/src/gui/platforms/s60/qclipboard_s60.cpp deleted file mode 100644 index 0dafae0996..0000000000 --- a/src/gui/platforms/s60/qclipboard_s60.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qclipboard.h" - -#ifndef QT_NO_CLIPBOARD - -#include "qapplication.h" -#include "qbitmap.h" -#include "qdatetime.h" -#include "qbuffer.h" -#include "qwidget.h" -#include "qevent.h" -#include "private/qcore_symbian_p.h" -#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS -#include "txtclipboard.h" -#endif -#include "txtetext.h" -#include <QtDebug> - -// Symbian's clipboard -#include <baclipb.h> -QT_BEGIN_NAMESPACE - -const TUid KQtCbDataStream = {0x2001B2DD}; -const TInt KPlainTextBegin = 0; - -class QClipboardData -{ -public: - QClipboardData(); - ~QClipboardData(); - - void setSource(QMimeData* s) - { - if (s == src) - return; - delete src; - src = s; - } - QMimeData* source() - { return src; } - bool connected() - { return connection; } - void clear(); - -private: - QMimeData* src; - bool connection; -}; - -QClipboardData::QClipboardData():src(0),connection(true) -{ - clear(); -} - -QClipboardData::~QClipboardData() -{ - connection = false; - delete src; -} - -void QClipboardData::clear() -{ - QMimeData* newSrc = new QMimeData; - delete src; - src = newSrc; -} - -static QClipboardData *internalCbData = 0; - -static void cleanupClipboardData() -{ - delete internalCbData; - internalCbData = 0; -} - -static QClipboardData *clipboardData() -{ - if (internalCbData == 0) { - internalCbData = new QClipboardData; - if (internalCbData) - { - if (!internalCbData->connected()) - { - delete internalCbData; - internalCbData = 0; - } - else - { - qAddPostRoutine(cleanupClipboardData); - } - } - } - return internalCbData; -} - -void writeToStreamLX(const QMimeData* aData, RWriteStream& aStream) -{ - // This function both leaves and throws exceptions. There must be no destructor - // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. - QStringList headers = aData->formats(); - aStream << TCardinality(headers.count()); - for (QStringList::const_iterator iter= headers.constBegin();iter != headers.constEnd();iter++) - { - HBufC* stringData = TPtrC(reinterpret_cast<const TUint16*>((*iter).utf16())).AllocLC(); - QByteArray ba = aData->data((*iter)); - // mime type - aStream << TCardinality(stringData->Size()); - aStream << *(stringData); - // mime data - aStream << TCardinality(ba.size()); - aStream.WriteL(reinterpret_cast<const uchar*>(ba.constData()),ba.size()); - CleanupStack::PopAndDestroy(stringData); - } -} - -void writeToSymbianStoreLX(const QMimeData* aData, CClipboard* clipboard) -{ - // This function both leaves and throws exceptions. There must be no destructor - // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. - if (aData->hasText()) { - CPlainText* text = CPlainText::NewL(); - CleanupStack::PushL(text); - - TPtrC textPtr(qt_QString2TPtrC(aData->text())); - text->InsertL(KPlainTextBegin, textPtr); - text->CopyToStoreL(clipboard->Store(), clipboard->StreamDictionary(), - KPlainTextBegin, textPtr.Length()); - CleanupStack::PopAndDestroy(text); - } -} - -void readSymbianStoreLX(QMimeData* aData, CClipboard* clipboard) -{ - // This function both leaves and throws exceptions. There must be no destructor - // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. - CPlainText* text = CPlainText::NewL(); - CleanupStack::PushL(text); - TInt dataLength = text->PasteFromStoreL(clipboard->Store(), clipboard->StreamDictionary(), - KPlainTextBegin); - if (dataLength == 0) { - User::Leave(KErrNotFound); - } - HBufC* hBuf = HBufC::NewL(dataLength); - TPtr buf = hBuf->Des(); - text->Extract(buf, KPlainTextBegin, dataLength); - - QString string = qt_TDesC2QString(buf); - CleanupStack::PopAndDestroy(text); - - aData->setText(string); -} - -void readFromStreamLX(QMimeData* aData,RReadStream& aStream) -{ - // This function both leaves and throws exceptions. There must be no destructor - // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. - TCardinality mimeTypeCount; - aStream >> mimeTypeCount; - for (int i = 0; i< mimeTypeCount;i++) - { - // mime type - TCardinality mimeTypeSize; - aStream >> mimeTypeSize; - HBufC* mimeTypeBuf = HBufC::NewLC(aStream,mimeTypeSize); - QString mimeType = QString(reinterpret_cast<const QChar *>(mimeTypeBuf->Des().Ptr()), - mimeTypeBuf->Length()); - CleanupStack::PopAndDestroy(mimeTypeBuf); - // mime data - TCardinality dataSize; - aStream >> dataSize; - QByteArray ba; - ba.reserve(dataSize); - aStream.ReadL(reinterpret_cast<uchar*>(ba.data_ptr()->data),dataSize); - ba.data_ptr()->size = dataSize; - aData->setData(mimeType,ba); - } -} - - -/***************************************************************************** - QClipboard member functions - *****************************************************************************/ - -void QClipboard::clear(Mode mode) -{ - setText(QString(), mode); -} -const QMimeData* QClipboard::mimeData(Mode mode) const -{ - if (mode != Clipboard) return 0; - QClipboardData *d = clipboardData(); - bool dataExists(false); - if (d) - { - TRAPD(err,{ - RFs fs = qt_s60GetRFs(); - CClipboard* cb = CClipboard::NewForReadingLC(fs); - Q_ASSERT(cb); - //stream for qt - RStoreReadStream stream; - TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream); - if (stid != 0) { - stream.OpenLC(cb->Store(),stid); - QT_TRYCATCH_LEAVING(readFromStreamLX(d->source(),stream)); - CleanupStack::PopAndDestroy(&stream); - dataExists = true; - } - else { - //symbian clipboard - RStoreReadStream symbianStream; - TStreamId symbianStId = (cb->StreamDictionary()).At(KClipboardUidTypePlainText); - if (symbianStId != 0) { - symbianStream.OpenLC(cb->Store(), symbianStId); - QT_TRYCATCH_LEAVING(readSymbianStoreLX(d->source(), cb)); - CleanupStack::PopAndDestroy(&symbianStream); - dataExists = true; - } - } - CleanupStack::PopAndDestroy(cb); - }); - if (err != KErrNone){ - qDebug()<< "clipboard is empty/err: " << err; - } - - if (dataExists) { - return d->source(); - } - } - return 0; -} - - -void QClipboard::setMimeData(QMimeData* src, Mode mode) -{ - if (mode != Clipboard) return; - QClipboardData *d = clipboardData(); - if (d) - { - TRAPD(err,{ - RFs fs = qt_s60GetRFs(); - CClipboard* cb = CClipboard::NewForWritingLC(fs); - //stream for qt - RStoreWriteStream stream; - TStreamId stid = stream.CreateLC(cb->Store()); - QT_TRYCATCH_LEAVING(writeToStreamLX(src,stream)); - d->setSource(src); - stream.CommitL(); - (cb->StreamDictionary()).AssignL(KQtCbDataStream,stid); - cb->CommitL(); - - //stream for symbian - RStoreWriteStream symbianStream; - TStreamId symbianStId = symbianStream.CreateLC(cb->Store()); - QT_TRYCATCH_LEAVING(writeToSymbianStoreLX(src, cb)); - (cb->StreamDictionary()).AssignL(KClipboardUidTypePlainText, symbianStId); - cb->CommitL(); - CleanupStack::PopAndDestroy(3,cb); - }); - if (err != KErrNone){ - qDebug()<< "clipboard write err :" << err; - } - } - emitChanged(QClipboard::Clipboard); -} - -bool QClipboard::supportsMode(Mode mode) const -{ - return (mode == Clipboard); -} - -bool QClipboard::ownsMode(Mode mode) const -{ - if (mode == Clipboard) - qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!"); - return false; -} - -bool QClipboard::event(QEvent * /* e */) -{ - return true; -} - -void QClipboard::connectNotify( const char * ) -{ -} - -void QClipboard::ownerDestroyed() -{ -} -QT_END_NAMESPACE -#endif // QT_NO_CLIPBOARD diff --git a/src/gui/platforms/s60/qcolormap_s60.cpp b/src/gui/platforms/s60/qcolormap_s60.cpp deleted file mode 100644 index 2c634db8a5..0000000000 --- a/src/gui/platforms/s60/qcolormap_s60.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcolormap.h" -#include "qcolor.h" - -QT_BEGIN_NAMESPACE - -class QColormapPrivate -{ -public: - inline QColormapPrivate() - : ref(1) - { } - - QAtomicInt ref; -}; - -void QColormap::initialize() -{ -} - -void QColormap::cleanup() -{ -} - -QColormap QColormap::instance(int) -{ - return QColormap(); -} - -QColormap::QColormap() : d(new QColormapPrivate) -{} - -QColormap::QColormap(const QColormap &colormap) :d (colormap.d) -{ d->ref.ref(); } - -QColormap::~QColormap() -{ - if (!d->ref.deref()) - delete d; -} - -QColormap::Mode QColormap::mode() const -{ return QColormap::Direct; } - -int QColormap::depth() const -{ - return 32; -} - -int QColormap::size() const -{ - return -1; -} - -uint QColormap::pixel(const QColor &color) const -{ return color.rgba(); } - -const QColor QColormap::colorAt(uint pixel) const -{ return QColor(pixel); } - -const QVector<QColor> QColormap::colormap() const -{ return QVector<QColor>(); } - -QColormap &QColormap::operator=(const QColormap &colormap) -{ qAtomicAssign(d, colormap.d); return *this; } - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qcursor_s60.cpp b/src/gui/platforms/s60/qcursor_s60.cpp deleted file mode 100644 index 8dfe87ef81..0000000000 --- a/src/gui/platforms/s60/qcursor_s60.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qcursor_p.h> -#include <private/qwidget_p.h> -#include <private/qapplication_p.h> -#include <coecntrl.h> -#include <qcursor.h> -#include <private/qt_s60_p.h> -#include <qbitmap.h> -#include <w32std.h> -#include <qapplication.h> -#include <qwidget.h> - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_CURSOR -static QCursor cursorSprite; -static int cursorSpriteVisible; -#endif - -//pos and setpos are required whether cursors are configured or not. -QPoint QCursor::pos() -{ - return S60->lastCursorPos; -} - -void QCursor::setPos(int x, int y) -{ - //clip to screen size (window server allows a sprite hotspot to be outside the screen) - if (x < 0) - x=0; - else if (x >= S60->screenWidthInPixels) - x = S60->screenWidthInPixels - 1; - if (y < 0) - y = 0; - else if (y >= S60->screenHeightInPixels) - y = S60->screenHeightInPixels - 1; - -#ifndef QT_NO_CURSOR -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors && cursorSpriteVisible) - cursorSprite.d->scurs.SetPosition(TPoint(x,y)); - else -#endif - S60->wsSession().SetPointerCursorPosition(TPoint(x, y)); -#endif - S60->lastCursorPos = QPoint(x, y); - //send a fake mouse move event, so that enter/leave events go to the widget hierarchy - QWidget *w = QApplication::topLevelAt(S60->lastCursorPos); - if (w) { - CCoeControl* ctrl = w->effectiveWinId(); - TPoint epos(x, y); - TPoint cpos = epos - ctrl->PositionRelativeToScreen(); - TPointerEvent fakeEvent; - fakeEvent.iType = TPointerEvent::EMove; - fakeEvent.iModifiers = 0U; - fakeEvent.iPosition = cpos; - fakeEvent.iParentPosition = epos; - ctrl->HandlePointerEventL(fakeEvent); - } -} - -#ifndef QT_NO_CURSOR -/* - * Request cursor to be turned on or off. - * Reference counted, so 2 on + 1 off = on, for example - */ -void qt_symbian_set_cursor_visible(bool visible) { - if (visible) - cursorSpriteVisible++; - else - cursorSpriteVisible--; - Q_ASSERT(cursorSpriteVisible >=0); - - if (cursorSpriteVisible && !S60->mouseInteractionEnabled) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_show_pointer_sprite(); - else -#endif - S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); - } else if (!cursorSpriteVisible && S60->mouseInteractionEnabled) { -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_hide_pointer_sprite(); - else -#endif - S60->wsSession().SetPointerCursorMode(EPointerCursorNone); - } - S60->mouseInteractionEnabled = ((cursorSpriteVisible > 0) ? true : false); -} - -/* - * Check if the cursor is on or off - */ -bool qt_symbian_is_cursor_visible() { - return S60->mouseInteractionEnabled; -} - -QCursorData::QCursorData(Qt::CursorShape s) : - cshape(s), bm(0), bmm(0), hx(0), hy(0), pcurs() -{ - ref = 1; -} - -QCursorData::~QCursorData() -{ - for(int i=0;i<nativeSpriteMembers.Count();i++) { - delete nativeSpriteMembers[i]->iBitmap; - delete nativeSpriteMembers[i]->iMaskBitmap; - } - nativeSpriteMembers.ResetAndDestroy(); - pcurs.Close(); - delete bm; - delete bmm; -} - -/* Create a bitmap cursor, this is called by public constructors in the - * generic QCursor code. - */ -QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { - qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); - QCursorData *c = qt_cursorTable[0]; - c->ref.ref(); - return c; - } - QCursorData *d = new QCursorData; - d->bm = new QBitmap(bitmap); - d->bmm = new QBitmap(mask); - d->cshape = Qt::BitmapCursor; - d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; - d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; - return d; -} - -/* - * returns an opaque native handle to a cursor. - * It happens to be the address of the native handle, as window server handles - * are not POD types. Note there is no QCursor(HANDLE) constructor on Symbian, - * Mac or QWS. - */ -Qt::HANDLE QCursor::handle() const -{ - if (d->pcurs.WsHandle()) - return reinterpret_cast<Qt::HANDLE> (&(d->pcurs)); - -#ifdef Q_SYMBIAN_HAS_SYSTEM_CURSORS - // don't construct shape cursors, QApplication_s60 will use the system cursor instead - if (!(d->bm)) - return 0; -#endif - - d->pcurs = RWsPointerCursor(S60->wsSession()); - d->pcurs.Construct(0); - d->constructCursorSprite(d->pcurs); - d->pcurs.Activate(); - - return reinterpret_cast<Qt::HANDLE> (&(d->pcurs)); -} - -#ifndef Q_SYMBIAN_HAS_SYSTEM_CURSORS -/* - * Loads a single cursor shape from resources and appends it to a native sprite. - * Animated cursors (e.g. the busy cursor) have multiple members. - */ -void QCursorData::loadShapeFromResource(RWsSpriteBase& target, QString resource, int hx, int hy, int interval) -{ - QPixmap pix; - CFbsBitmap* native; - QScopedPointer<TSpriteMember> member(new TSpriteMember); - member->iInterval = interval; - member->iInvertMask = false; - member->iMaskBitmap = 0; // all shapes are RGBA - member->iDrawMode = CGraphicsContext::EDrawModePEN; - member->iOffset = TPoint(-hx, -hy); - QString res(QLatin1String(":/trolltech/symbian/cursors/images/%1.png")); - pix.load(res.arg(resource)); - native = pix.toSymbianCFbsBitmap(); - member->iBitmap = native; - qt_symbian_throwIfError(nativeSpriteMembers.Append(member.data())); - target.AppendMember(*(member.take())); -} - -//TODO: after 4.6, connect with style & skins? -/* - * Constructs the native cursor from resources compiled into QtGui - * This is needed only when the platform doesn't have system cursors. - * - * System cursors are higher performance, since they are constructed once - * and shared by all applications by specifying the shape number. - * Due to symbian platform security considerations, and the fact most - * existing phones have a broken RWsPointerCursor, system cursors are not - * being used. - */ -void QCursorData::constructShapeSprite(RWsSpriteBase& target) -{ - int i; - switch (cshape) { - default: - qWarning("QCursorData::constructShapeSprite unknown shape %d", cshape); - //fall through and give arrow cursor - case Qt::ArrowCursor: - loadShapeFromResource(target, QLatin1String("pointer"), 1, 1); - break; - case Qt::UpArrowCursor: - loadShapeFromResource(target, QLatin1String("uparrow"), 4, 0); - break; - case Qt::CrossCursor: - loadShapeFromResource(target, QLatin1String("cross"), 7, 7); - break; - case Qt::WaitCursor: - for (i = 1; i <= 12; i++) { - loadShapeFromResource(target, QString(QLatin1String("wait%1")).arg(i), 7, 7, 1000000); - } - break; - case Qt::IBeamCursor: - loadShapeFromResource(target, QLatin1String("ibeam"), 3, 10); - break; - case Qt::SizeVerCursor: - loadShapeFromResource(target, QLatin1String("sizever"), 4, 8); - break; - case Qt::SizeHorCursor: - loadShapeFromResource(target, QLatin1String("sizehor"), 8, 4); - break; - case Qt::SizeBDiagCursor: - loadShapeFromResource(target, QLatin1String("sizebdiag"), 8, 8); - break; - case Qt::SizeFDiagCursor: - loadShapeFromResource(target, QLatin1String("sizefdiag"), 8, 8); - break; - case Qt::SizeAllCursor: - loadShapeFromResource(target, QLatin1String("sizeall"), 7, 7); - break; - case Qt::BlankCursor: - loadShapeFromResource(target, QLatin1String("blank"), 0, 0); - break; - case Qt::SplitVCursor: - loadShapeFromResource(target, QLatin1String("splitv"), 7, 7); - break; - case Qt::SplitHCursor: - loadShapeFromResource(target, QLatin1String("splith"), 7, 7); - break; - case Qt::PointingHandCursor: - loadShapeFromResource(target, QLatin1String("handpoint"), 5, 0); - break; - case Qt::ForbiddenCursor: - loadShapeFromResource(target, QLatin1String("forbidden"), 7, 7); - break; - case Qt::WhatsThisCursor: - loadShapeFromResource(target, QLatin1String("whatsthis"), 1, 1); - break; - case Qt::BusyCursor: - loadShapeFromResource(target, QLatin1String("busy3"), 1, 1, 1000000); - loadShapeFromResource(target, QLatin1String("busy6"), 1, 1, 1000000); - loadShapeFromResource(target, QLatin1String("busy9"), 1, 1, 1000000); - loadShapeFromResource(target, QLatin1String("busy12"), 1, 1, 1000000); - break; - case Qt::OpenHandCursor: - loadShapeFromResource(target, QLatin1String("openhand"), 7, 7); - break; - case Qt::ClosedHandCursor: - loadShapeFromResource(target, QLatin1String("closehand"), 7, 7); - break; - } -} -#endif - -/* - * Common code between the sprite workaround and standard modes of operation. - * RWsSpriteBase is the base class for both RWsSprite and RWsPointerCursor. - * It is called from both handle() and qt_s60_show_pointer_sprite() - */ -void QCursorData::constructCursorSprite(RWsSpriteBase& target) -{ - int count = nativeSpriteMembers.Count(); - if (count) { - // already constructed - for (int i = 0; i < count; i++) - target.AppendMember(*(nativeSpriteMembers[i])); - - return; - } - if (pixmap.isNull() && !bm) { -#ifndef Q_SYMBIAN_HAS_SYSTEM_CURSORS - //shape cursor - constructShapeSprite(target); -#endif - return; - } - QScopedPointer<TSpriteMember> member(new TSpriteMember); - if (pixmap.isNull()) { - //construct mono cursor - member->iBitmap = bm->toSymbianCFbsBitmap(); - member->iMaskBitmap = bmm->toSymbianCFbsBitmap(); - } - else { - //construct normal cursor - member->iBitmap = pixmap.toSymbianCFbsBitmap(); - if (pixmap.hasAlphaChannel()) { - member->iMaskBitmap = 0; //use alpha blending - } - else if (pixmap.hasAlpha()) { - member->iMaskBitmap = pixmap.mask().toSymbianCFbsBitmap(); - } - else { - member->iMaskBitmap = 0; //opaque rectangle cursor (due to EDrawModePEN) - } - } - - member->iDrawMode = CGraphicsContext::EDrawModePEN; - member->iInvertMask = EFalse; - member->iInterval = 0; - member->iOffset = TPoint(-(hx), -(hy)); //Symbian hotspot coordinates are negative - qt_symbian_throwIfError(nativeSpriteMembers.Append(member.data())); - target.AppendMember(*(member.take())); -} - -/* - * shows the pointer sprite by constructing a native handle, and registering - * it with the window server. - * Only used when the sprite workaround is in use. - */ -void qt_symbian_show_pointer_sprite() -{ - if (cursorSprite.d) { - if (cursorSprite.d->scurs.WsHandle()) - cursorSprite.d->scurs.Close(); - } else { - cursorSprite = QCursor(Qt::ArrowCursor); - } - - cursorSprite.d->scurs = RWsSprite(S60->wsSession()); - QPoint pos = QCursor::pos(); - cursorSprite.d->scurs.Construct(S60->windowGroup(), TPoint(pos.x(), pos.y()), ESpriteNoChildClip | ESpriteNoShadows); - - cursorSprite.d->constructCursorSprite(cursorSprite.d->scurs); - cursorSprite.d->scurs.Activate(); -} - -/* - * hides the pointer sprite by closing the native handle. - * Only used when the sprite workaround is in use. - */ -void qt_symbian_hide_pointer_sprite() -{ - if (cursorSprite.d) { - cursorSprite.d->scurs.Close(); - } -} - -/* - * Changes the cursor sprite to the cursor specified. - * Only used when the sprite workaround is in use. - */ -void qt_symbian_set_pointer_sprite(const QCursor& cursor) -{ - if (S60->mouseInteractionEnabled) - qt_symbian_hide_pointer_sprite(); - cursorSprite = cursor; - if (S60->mouseInteractionEnabled) - qt_symbian_show_pointer_sprite(); -} - -/* - * When using sprites as a workaround on phones that have a broken - * RWsPointerCursor, this function is called in response to pointer events - * and when QCursor::setPos() is called. - * Performance is worse than a real pointer cursor, due to extra context - * switches vs. the window server moving the cursor by itself. - */ -void qt_symbian_move_cursor_sprite() -{ - if (S60->mouseInteractionEnabled) { - cursorSprite.d->scurs.SetPosition(TPoint(S60->lastCursorPos.x(), S60->lastCursorPos.y())); - } -} - -/* - * Translate from Qt::CursorShape to OS system pointer cursor list index. - * Currently we control the implementation of the system pointer cursor list, - * so this function is trivial. That may not always be the case. - */ -TInt qt_symbian_translate_cursor_shape(Qt::CursorShape shape) -{ - return (TInt) shape; -} - -/* - Internal function called from QWidget::setCursor() - force is true if this function is called from dispatchEnterLeave, it means that the - mouse is actually directly under this widget. -*/ -void qt_symbian_set_cursor(QWidget *w, bool force) -{ - static QPointer<QWidget> lastUnderMouse = 0; - if (force) { - lastUnderMouse = w; - } - else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse - && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) { - w = lastUnderMouse; - } - - if (!S60->curWin && w && w->internalWinId()) - return; - QWidget* cW = w && !w->internalWinId() ? w : QWidget::find(S60->curWin); - if (!cW || cW->window() != w->window() || !cW->isVisible() || !cW->underMouse() - || QApplication::overrideCursor()) - return; - -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) - qt_symbian_set_pointer_sprite(cW->cursor()); - else -#endif - qt_symbian_setWindowCursor(cW->cursor(), w->effectiveWinId()); -} - -/* - * Makes the specified cursor appear above a specific native window group - * Called from QSymbianControl and QApplication::restoreOverrideCursor - * - * Window server is needed for this, so there is no equivalent when using - * the sprite workaround. - */ -void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &node) -{ - Qt::HANDLE handle = cursor.handle(); - if (handle) { - RWsPointerCursor *pcurs = reinterpret_cast<RWsPointerCursor *> (handle); - node.SetCustomPointerCursor(*pcurs); - } else -#ifdef Q_SYMBIAN_HAS_SYSTEM_CURSORS - { - TInt shape = qt_symbian_translate_cursor_shape(cursor.shape()); - node.SetPointerCursor(shape); - } -#else - qWarning("qt_s60_setWindowGroupCursor - null handle"); -#endif -} - -/* - * Makes the specified cursor appear above a specific native window - * Called from QSymbianControl and QApplication::restoreOverrideCursor - * - * Window server is needed for this, so there is no equivalent when using - * the sprite workaround. - */ -void qt_symbian_setWindowCursor(const QCursor &cursor, const CCoeControl* wid) -{ - //find the window for this control - while (!wid->OwnsWindow()) { - wid = wid->Parent(); - if (!wid) - return; - } - RWindowTreeNode *node = wid->DrawableWindow(); - qt_symbian_setWindowGroupCursor(cursor, *node); -} - -/* - * Makes the specified cursor appear everywhere. - * Called from QApplication::setOverrideCursor - */ -void qt_symbian_setGlobalCursor(const QCursor &cursor) -{ -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - if (S60->brokenPointerCursors) { - qt_symbian_set_pointer_sprite(cursor); - } else -#endif - { - //because of the internals of window server, we need to force the cursor - //to be set in all child windows too, otherwise when the cursor is over - //the child window it may show a widget cursor or arrow cursor instead, - //depending on construction order. - QListIterator<WId> iter(QWidgetPrivate::mapper->uniqueKeys()); - while(iter.hasNext()) - { - CCoeControl *ctrl = iter.next(); - if(ctrl->OwnsWindow()) { - RWindowTreeNode *node = ctrl->DrawableWindow(); - qt_symbian_setWindowGroupCursor(cursor, *node); - } - } - } -} -QT_END_NAMESPACE -#endif // QT_NO_CURSOR diff --git a/src/gui/platforms/s60/qdesktopwidget_s60.cpp b/src/gui/platforms/s60/qdesktopwidget_s60.cpp deleted file mode 100644 index 62a4d40eba..0000000000 --- a/src/gui/platforms/s60/qdesktopwidget_s60.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdesktopwidget.h" -#include "qapplication_p.h" -#include "qwidget_p.h" -#include "qt_s60_p.h" -#include <w32std.h> -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) -#include <graphics/displaycontrol.h> -#endif - -QT_BEGIN_NAMESPACE - -extern int qt_symbian_create_desktop_on_screen; - -class QSingleDesktopWidget : public QWidget -{ -public: - QSingleDesktopWidget(); - ~QSingleDesktopWidget(); -}; - -QSingleDesktopWidget::QSingleDesktopWidget() - : QWidget(0, Qt::Desktop) -{ -} - -QSingleDesktopWidget::~QSingleDesktopWidget() -{ - const QObjectList &childList = children(); - for (int i = childList.size(); i > 0 ;) { - --i; - childList.at(i)->setParent(0); - } -} - -class QDesktopWidgetPrivate : public QWidgetPrivate -{ -public: - QDesktopWidgetPrivate(); - ~QDesktopWidgetPrivate(); - static void init(QDesktopWidget *that); - static void cleanup(); - static void init_sys(); - - static int screenCount; - static int primaryScreen; - - static QVector<QRect> *rects; - static QVector<QRect> *workrects; - static QVector<QWidget *> *screens; - - static int refcount; - -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - static MDisplayControl *displayControl; -#endif -}; - -int QDesktopWidgetPrivate::screenCount = 1; -int QDesktopWidgetPrivate::primaryScreen = 0; -QVector<QRect> *QDesktopWidgetPrivate::rects = 0; -QVector<QRect> *QDesktopWidgetPrivate::workrects = 0; -QVector<QWidget *> *QDesktopWidgetPrivate::screens = 0; -int QDesktopWidgetPrivate::refcount = 0; -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) -MDisplayControl *QDesktopWidgetPrivate::displayControl = 0; -#endif - -QDesktopWidgetPrivate::QDesktopWidgetPrivate() -{ - ++refcount; -} - -QDesktopWidgetPrivate::~QDesktopWidgetPrivate() -{ - if (!--refcount) - cleanup(); -} - -void QDesktopWidgetPrivate::init(QDesktopWidget *that) -{ - // Note that on S^3 devices the screen count retrieved via RWsSession - // will always be 2 but the width and height for screen number 1 will - // be 0 as long as TV-out is not connected. - // - // On the other hand a valid size for screen 1 will be reported even - // after the cable is disconnected. In order to overcome this, we use - // MDisplayControl::NumberOfResolutions() to check if the display is - // valid or not. - - screenCount = S60->screenCount(); -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - if (displayControl) { - if (displayControl->NumberOfResolutions() < 1) - screenCount = 1; - } -#endif - if (screenCount < 1) { - qWarning("No screen available"); - screenCount = 1; - } - - rects = new QVector<QRect>(); - workrects = new QVector<QRect>(); - screens = new QVector<QWidget *>(); - - rects->resize(screenCount); - workrects->resize(screenCount); - screens->resize(screenCount); - - for (int i = 0; i < screenCount; ++i) { - // All screens will have a position of (0, 0) as there is no true virtual desktop - // or pointer event support for multiple screens on Symbian. - QRect r(0, 0, - S60->screenWidthInPixelsForScreen[i], S60->screenHeightInPixelsForScreen[i]); - // Stop here if empty and ignore this screen. - if (r.isEmpty()) { - screenCount = i; - break; - } - (*rects)[i] = r; - QRect wr; - if (i == 0) - wr = qt_TRect2QRect(static_cast<CEikAppUi*>(S60->appUi())->ClientRect()); - else - wr = rects->at(i); - (*workrects)[i].setRect(wr.x(), wr.y(), wr.width(), wr.height()); - (*screens)[i] = 0; - } - (*screens)[0] = that; -} - -void QDesktopWidgetPrivate::cleanup() -{ - delete rects; - rects = 0; - delete workrects; - workrects = 0; - if (screens) { - // First item is the QDesktopWidget so skip it. - for (int i = 1; i < screens->count(); ++i) - delete screens->at(i); - } - delete screens; - screens = 0; -} - -void QDesktopWidgetPrivate::init_sys() -{ -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - if (S60->screenCount() > 1) { - CWsScreenDevice *dev = S60->screenDevice(1); - if (dev) { - displayControl = static_cast<MDisplayControl *>( - dev->GetInterface(MDisplayControl::ETypeId)); - if (displayControl) { - displayControl->EnableDisplayChangeEvents(ETrue); - } - } - } -#endif -} - - -QDesktopWidget::QDesktopWidget() - : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) -{ - setObjectName(QLatin1String("desktop")); - QDesktopWidgetPrivate::init_sys(); - QDesktopWidgetPrivate::init(this); -} - -QDesktopWidget::~QDesktopWidget() -{ -} - -bool QDesktopWidget::isVirtualDesktop() const -{ - return false; -} - -int QDesktopWidget::primaryScreen() const -{ - return QDesktopWidgetPrivate::primaryScreen; -} - -int QDesktopWidget::numScreens() const -{ - Q_D(const QDesktopWidget); - return QDesktopWidgetPrivate::screenCount; -} - -static inline QWidget *newSingleDesktopWidget(int screen) -{ - qt_symbian_create_desktop_on_screen = screen; - QWidget *w = new QSingleDesktopWidget; - qt_symbian_create_desktop_on_screen = -1; - return w; -} - -QWidget *QDesktopWidget::screen(int screen) -{ - Q_D(QDesktopWidget); - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; - if (!d->screens->at(screen) - || d->screens->at(screen)->windowType() != Qt::Desktop) - (*d->screens)[screen] = newSingleDesktopWidget(screen); - return (*d->screens)[screen]; -} - -const QRect QDesktopWidget::availableGeometry(int screen) const -{ - Q_D(const QDesktopWidget); - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; - - return d->workrects->at(screen); -} - -const QRect QDesktopWidget::screenGeometry(int screen) const -{ - Q_D(const QDesktopWidget); - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; - - return d->rects->at(screen); -} - -int QDesktopWidget::screenNumber(const QWidget *widget) const -{ - Q_D(const QDesktopWidget); - return widget - ? S60->screenNumberForWidget(widget) - : d->primaryScreen; -} - -int QDesktopWidget::screenNumber(const QPoint &point) const -{ - Q_UNUSED(point); - Q_D(const QDesktopWidget); - return d->primaryScreen; -} - -void QDesktopWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QDesktopWidget); - QVector<QRect> oldrects; - oldrects = *d->rects; - QVector<QRect> oldworkrects; - oldworkrects = *d->workrects; - int oldscreencount = d->screenCount; - - QDesktopWidgetPrivate::cleanup(); - QDesktopWidgetPrivate::init(this); - - for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { - QRect oldrect = oldrects[i]; - QRect newrect = d->rects->at(i); - if (oldrect != newrect) - emit resized(i); - } - - for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { - QRect oldrect = oldworkrects[j]; - QRect newrect = d->workrects->at(j); - if (oldrect != newrect) - emit workAreaResized(j); - } - - if (oldscreencount != d->screenCount) { - emit screenCountChanged(d->screenCount); - } -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qdnd_s60.cpp b/src/gui/platforms/s60/qdnd_s60.cpp deleted file mode 100644 index a9847a98f8..0000000000 --- a/src/gui/platforms/s60/qdnd_s60.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" - -#ifndef QT_NO_DRAGANDDROP - -#include "qwidget.h" -#include "qdatetime.h" -#include "qbitmap.h" -#include "qcursor.h" -#include "qevent.h" -#include "qpainter.h" -#include "qdnd_p.h" -#include "qt_s60_p.h" - -#include <coecntrl.h> -// pointer cursor -#include <w32std.h> -#include <gdi.h> -#include <QCursor> - -QT_BEGIN_NAMESPACE -//### artistic impression of Symbians default DnD cursor ? - -static QPixmap *defaultPm = 0; -static const int default_pm_hotx = -50; -static const int default_pm_hoty = -50; -static const char *const default_pm[] = { -"13 9 3 1", -". c None", -" c #000000", -"X c #FFFFFF", -"X X X X X X X", -" X X X X X X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X X X X X X ", -"X X X X X X X", -}; -//### actions need to be redefined for S60 -// Shift/Ctrl handling, and final drop status -static Qt::DropAction global_accepted_action = Qt::MoveAction; -static Qt::DropActions possible_actions = Qt::IgnoreAction; - - -// static variables in place of a proper cross-process solution -static QDrag *drag_object; -static bool qt_symbian_dnd_dragging = false; - - -static Qt::KeyboardModifiers oldstate; - -void QDragManager::updatePixmap() -{ - QPixmap pm; - QPoint pm_hot(default_pm_hotx,default_pm_hoty); - if (drag_object) { - pm = drag_object->pixmap(); - if (!pm.isNull()) - pm_hot = drag_object->hotSpot(); - } - if (pm.isNull()) { - if (!defaultPm) - defaultPm = new QPixmap(default_pm); - pm = *defaultPm; - } -#ifndef QT_NO_CURSOR - QCursor cursor(pm, pm_hot.x(), pm_hot.y()); - overrideCursor = cursor; -#endif -} - -void QDragManager::timerEvent(QTimerEvent *) { } - -void QDragManager::move(const QPoint&) { -} - -void QDragManager::updateCursor() -{ -#ifndef QT_NO_CURSOR - QCursor cursor = willDrop ? overrideCursor : Qt::ForbiddenCursor; - if (!restoreCursor) { - QApplication::setOverrideCursor(cursor); - restoreCursor = true; - } - else { - QApplication::changeOverrideCursor(cursor); - } -#endif -} - - -bool QDragManager::eventFilter(QObject *o, QEvent *e) -{ - if (beingCancelled) { - return false; - } - if (!o->isWidgetType()) - return false; - - switch(e->type()) { - case QEvent::MouseButtonPress: - { - } - case QEvent::MouseMove: - { - if (!object) { //#### this should not happen - qWarning("QDragManager::eventFilter: No object"); - return true; - } - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; - if (manager->object) - possible_actions = manager->dragPrivate()->possible_actions; - else - possible_actions = Qt::IgnoreAction; - - QMouseEvent *me = (QMouseEvent *)e; - - if (me->buttons()) { - Qt::DropAction prevAction = global_accepted_action; - QWidget *cw = QApplication::widgetAt(me->globalPos()); - // map the Coords relative to the window. - if (!cw) - return true; - - while (cw && !cw->acceptDrops() && !cw->isWindow()) - cw = cw->parentWidget(); - - bool oldWillDrop = willDrop; - if (object->target() != cw) { - if (object->target()) { - QDragLeaveEvent dle; - QApplication::sendEvent(object->target(), &dle); - willDrop = false; - global_accepted_action = Qt::IgnoreAction; - if (oldWillDrop != willDrop) - updateCursor(); - object->d_func()->target = 0; - } - if (cw && cw->acceptDrops()) { - object->d_func()->target = cw; - QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); - QApplication::sendEvent(object->target(), &dee); - willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; - global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction; - if (oldWillDrop != willDrop) - updateCursor(); - } - } else if (cw) { - QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); - if (global_accepted_action != Qt::IgnoreAction) { - dme.setDropAction(global_accepted_action); - dme.accept(); - } - QApplication::sendEvent(cw, &dme); - willDrop = dme.isAccepted(); - global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction; - if (oldWillDrop != willDrop) { - updatePixmap(); - updateCursor(); - } - } - if (global_accepted_action != prevAction) - emitActionChanged(global_accepted_action); - } - return true; // Eat all mouse events - } - - case QEvent::MouseButtonRelease: - { - qApp->removeEventFilter(this); -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - willDrop = false; - restoreCursor = false; - } -#endif - if (object && object->target()) { - - QMouseEvent *me = (QMouseEvent *)e; - - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; - - QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData, - me->buttons(), me->modifiers()); - QApplication::sendEvent(object->target(), &de); - if (de.isAccepted()) - global_accepted_action = de.dropAction(); - else - global_accepted_action = Qt::IgnoreAction; - - if (object) - object->deleteLater(); - drag_object = object = 0; - } - eventLoop->exit(); - return true; // Eat all mouse events - } - - default: - break; - } - return false; -} - -Qt::DropAction QDragManager::drag(QDrag *o) -{ - Q_ASSERT(!qt_symbian_dnd_dragging); - if (object == o || !o || !o->source()) - return Qt::IgnoreAction; - - if (object) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - } - - object = drag_object = o; - - oldstate = Qt::NoModifier; // #### Should use state that caused the drag - willDrop = false; - updatePixmap(); - updateCursor(); - -#ifndef QT_NO_CURSOR - qt_symbian_set_cursor_visible(true); //force cursor on even for touch phone -#endif - - object->d_func()->target = 0; - - qApp->installEventFilter(this); - - global_accepted_action = defaultAction(dragPrivate()->possible_actions, Qt::NoModifier); - qt_symbian_dnd_dragging = true; - - eventLoop = new QEventLoop; - // block - (void) eventLoop->exec(QEventLoop::AllEvents); - delete eventLoop; - eventLoop = 0; - -#ifndef QT_NO_CURSOR - qt_symbian_set_cursor_visible(false); - - overrideCursor = QCursor(); //deref the cursor data - qt_symbian_dnd_dragging = false; -#endif - - return global_accepted_action; -} - - -void QDragManager::cancel(bool deleteSource) -{ - beingCancelled = true; - - if (object->target()) { - QDragLeaveEvent dle; - QApplication::sendEvent(object->target(), &dle); - } - - if (drag_object) { - if (deleteSource) - object->deleteLater(); - drag_object = object = 0; - } - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif - - global_accepted_action = Qt::IgnoreAction; -} - - -void QDragManager::drop() -{ -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif -} - -QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const -{ - if (!drag_object) - return QVariant(); - QByteArray data = drag_object->mimeData()->data(mimetype); - if (type == QVariant::String) - return QString::fromUtf8(data); - return data; -} - -bool QDropData::hasFormat_sys(const QString &format) const -{ - return formats().contains(format); -} - -QStringList QDropData::formats_sys() const -{ - if (drag_object) - return drag_object->mimeData()->formats(); - return QStringList(); -} - -QT_END_NAMESPACE -#endif // QT_NO_DRAGANDDROP diff --git a/src/gui/platforms/s60/qeventdispatcher_s60.cpp b/src/gui/platforms/s60/qeventdispatcher_s60.cpp deleted file mode 100644 index 2d92c89c07..0000000000 --- a/src/gui/platforms/s60/qeventdispatcher_s60.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qwidget.h> - -#include "qeventdispatcher_s60_p.h" - -QT_BEGIN_NAMESPACE - -QtEikonEnv::QtEikonEnv() - : m_lastIterationCount(0) - , m_savedStatusCode(KRequestPending) - , m_hasAlreadyRun(false) -{ -} - -QtEikonEnv::~QtEikonEnv() -{ -} - -void QtEikonEnv::RunL() -{ - QEventDispatcherS60 *dispatcher = qobject_cast<QEventDispatcherS60 *>(QAbstractEventDispatcher::instance()); - if (!dispatcher) { - CEikonEnv::RunL(); - return; - } - - if (m_lastIterationCount != dispatcher->iterationCount()) { - m_hasAlreadyRun = false; - m_lastIterationCount = dispatcher->iterationCount(); - } - - if (m_hasAlreadyRun) { - // Fool the active scheduler into believing we are still waiting for events. - // The window server thinks we are not, however. - m_savedStatusCode = iStatus.Int(); - iStatus = KRequestPending; - SetActive(); - dispatcher->queueDeferredActiveObjectsCompletion(); - } else { - m_hasAlreadyRun = true; - CEikonEnv::RunL(); - } -} - -void QtEikonEnv::DoCancel() -{ - complete(); - - CEikonEnv::DoCancel(); -} - -void QtEikonEnv::complete() -{ - if (m_hasAlreadyRun) { - if (m_savedStatusCode != KRequestPending) { - TRequestStatus *status = &iStatus; - QEventDispatcherSymbian::RequestComplete(status, m_savedStatusCode); - m_savedStatusCode = KRequestPending; - } - m_hasAlreadyRun = false; - } -} - -QEventDispatcherS60::QEventDispatcherS60(QObject *parent) - : QEventDispatcherSymbian(parent), - m_noInputEvents(false) -{ -} - -QEventDispatcherS60::~QEventDispatcherS60() -{ - for (int c = 0; c < m_deferredInputEvents.size(); ++c) { - delete m_deferredInputEvents[c].event; - } -} - -bool QEventDispatcherS60::processEvents ( QEventLoop::ProcessEventsFlags flags ) -{ - bool ret = false; - - QT_TRY { - bool oldNoInputEventsValue = m_noInputEvents; - if (flags & QEventLoop::ExcludeUserInputEvents) { - m_noInputEvents = true; - } else { - m_noInputEvents = false; - ret = sendDeferredInputEvents() || ret; - } - - ret = QEventDispatcherSymbian::processEvents(flags) || ret; - - m_noInputEvents = oldNoInputEventsValue; - } QT_CATCH (const std::exception& ex) { -#ifndef QT_NO_EXCEPTIONS - CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex)); -#endif - } - - return ret; -} - -bool QEventDispatcherS60::hasPendingEvents() -{ - return !m_deferredInputEvents.isEmpty() || QEventDispatcherSymbian::hasPendingEvents(); -} - -void QEventDispatcherS60::saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event) -{ - DeferredInputEvent inputEvent = {control, widget, event}; - m_deferredInputEvents.append(inputEvent); - connect(widget, SIGNAL(destroyed(QObject*)), SLOT(removeInputEventsForWidget(QObject*))); -} - -bool QEventDispatcherS60::sendDeferredInputEvents() -{ - bool eventsSent = false; - while (!m_deferredInputEvents.isEmpty()) { - DeferredInputEvent inputEvent = m_deferredInputEvents.takeFirst(); -#ifndef QT_NO_EXCEPTIONS - try { -#endif - inputEvent.control->sendInputEvent(inputEvent.widget, inputEvent.event); -#ifndef QT_NO_EXCEPTIONS - } catch (...) { - delete inputEvent.event; - throw; - } -#endif - delete inputEvent.event; - eventsSent = true; - } - - return eventsSent; -} - -void QEventDispatcherS60::removeInputEventsForWidget(QObject *object) -{ - for (int c = 0; c < m_deferredInputEvents.size(); ++c) { - if (m_deferredInputEvents[c].widget == object) { - delete m_deferredInputEvents[c].event; - m_deferredInputEvents.removeAt(c--); - } - } -} - -// reimpl -void QEventDispatcherS60::reactivateDeferredActiveObjects() -{ - if (S60->qtOwnsS60Environment) { - static_cast<QtEikonEnv *>(CCoeEnv::Static())->complete(); - } - - QEventDispatcherSymbian::reactivateDeferredActiveObjects(); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qeventdispatcher_s60_p.h b/src/gui/platforms/s60/qeventdispatcher_s60_p.h deleted file mode 100644 index 7c5a8d03d4..0000000000 --- a/src/gui/platforms/s60/qeventdispatcher_s60_p.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QEVENTDISPATCHER_S60_P_H -#define QEVENTDISPATCHER_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qeventdispatcher_symbian_p.h> -#include "qt_s60_p.h" - -#include <eikenv.h> - -QT_BEGIN_NAMESPACE - -class QEventDispatcherS60; - -class QtEikonEnv : public CEikonEnv -{ -public: - QtEikonEnv(); - ~QtEikonEnv(); - - // from CActive. - void RunL(); - void DoCancel(); - - void complete(); - -private: - // Workaround for a BC break from S60 3.2 -> 5.0, where the CEikonEnv override was removed. - // To avoid linking to that when we build against 3.2, define an empty body here. - // Reserved_*() have been verified to be empty in the S60 code. - void Reserved_1() {} - void Reserved_2() {} - -private: - int m_lastIterationCount; - TInt m_savedStatusCode; - bool m_hasAlreadyRun; -}; - -class Q_GUI_EXPORT QEventDispatcherS60 : public QEventDispatcherSymbian -{ - Q_OBJECT - -public: - QEventDispatcherS60(QObject *parent = 0); - ~QEventDispatcherS60(); - - bool processEvents ( QEventLoop::ProcessEventsFlags flags ); - bool hasPendingEvents(); - - bool excludeUserInputEvents() { return m_noInputEvents; } - - void saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event); - - void reactivateDeferredActiveObjects(); - -private: - bool sendDeferredInputEvents(); - -private Q_SLOTS: - void removeInputEventsForWidget(QObject *object); - -private: - bool m_noInputEvents; - - struct DeferredInputEvent - { - QSymbianControl *control; - QWidget *widget; - QInputEvent *event; - }; - QList<DeferredInputEvent> m_deferredInputEvents; -}; - -QT_END_NAMESPACE - -#endif // QEVENTDISPATCHER_S60_P_H diff --git a/src/gui/platforms/s60/qfont_s60.cpp b/src/gui/platforms/s60/qfont_s60.cpp deleted file mode 100644 index 114191d765..0000000000 --- a/src/gui/platforms/s60/qfont_s60.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfont.h" -#include "qfont_p.h" -#include <private/qt_s60_p.h> -#include <private/qpixmap_s60_p.h> -#include "qmutex.h" - -QT_BEGIN_NAMESPACE - -#ifdef QT_NO_FREETYPE -Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); -#endif // QT_NO_FREETYPE - -extern QStringList qt_symbian_fontFamiliesOnFontServer(); // qfontdatabase_s60.cpp -Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, fontFamiliesOnFontServer, { - // We are only interested in the initial font families. No Application fonts. - // Therefore, we are allowed to cache the list. - x->append(qt_symbian_fontFamiliesOnFontServer()); -}); - -QString QFont::lastResortFont() const -{ - // Symbian's font Api does not distinguish between font and family. - // Therefore we try to get a "Family" first, then fall back to "Sans". - static QString font = lastResortFamily(); - if (font.isEmpty()) - font = QLatin1String("Sans"); - return font; -} - -QString QFont::lastResortFamily() const -{ -#ifdef QT_NO_FREETYPE - QMutexLocker locker(lastResortFamilyMutex()); - static QString family; - if (family.isEmpty()) { - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - CFont *font; - const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); - Q_ASSERT(err == KErrNone); - const TFontSpec spec = font->FontSpecInTwips(); - family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length()); - S60->screenDevice()->ReleaseFont(font); - - lock.relock(); - } - return family; -#else // QT_NO_FREETYPE - // For the FreeType case we just hard code the face name, since otherwise on - // East Asian systems we may get a name for a stroke based (non-ttf) font. - - // TODO: Get the type face name in a proper way - - const bool isJapaneseOrChineseSystem = - User::Language() == ELangJapanese || User::Language() == ELangPrcChinese; - - static QString family; - if (family.isEmpty()) { - QStringList families = qt_symbian_fontFamiliesOnFontServer(); - const char* const preferredFamilies[] = {"Nokia Sans S60", "Series 60 Sans"}; - for (int i = 0; i < sizeof preferredFamilies / sizeof preferredFamilies[0]; ++i) { - const QString preferredFamily = QLatin1String(preferredFamilies[i]); - if (families.contains(preferredFamily)) { - family = preferredFamily; - break; - } - } - } - - return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":family.toLatin1()); -#endif // QT_NO_FREETYPE -} - -QString QFont::defaultFamily() const -{ -#ifdef QT_NO_FREETYPE - switch(d->request.styleHint) { - case QFont::SansSerif: { - static const char* const preferredSansSerif[] = {"Nokia Sans S60", "Series 60 Sans"}; - for (int i = 0; i < sizeof preferredSansSerif / sizeof preferredSansSerif[0]; ++i) { - const QString sansSerif = QLatin1String(preferredSansSerif[i]); - if (fontFamiliesOnFontServer()->contains(sansSerif)) - return sansSerif; - } - } - // No break. Intentional fall through. - default: - return lastResortFamily(); - } -#endif // QT_NO_FREETYPE - return lastResortFamily(); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qfontdatabase_s60.cpp b/src/gui/platforms/s60/qfontdatabase_s60.cpp deleted file mode 100644 index 1db4a7d359..0000000000 --- a/src/gui/platforms/s60/qfontdatabase_s60.cpp +++ /dev/null @@ -1,1091 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qapplication_p.h> -#include "qdir.h" -#include "qfont_p.h" -#include "qfontengine_s60_p.h" -#include "qabstractfileengine.h" -#include "qdesktopservices.h" -#include "qtemporaryfile.h" -#include "qtextcodec.h" -#include <private/qpixmap_s60_p.h> -#include <private/qt_s60_p.h> -#include "qendian.h" -#include <private/qcore_symbian_p.h> -#ifdef QT_NO_FREETYPE -#include <openfont.h> -#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS -#include <graphics/openfontrasterizer.h> // COpenFontRasterizer has moved to a new header file -#endif // SYMBIAN_ENABLE_SPLIT_HEADERS -#endif // QT_NO_FREETYPE - -QT_BEGIN_NAMESPACE - -QStringList qt_symbian_fontFamiliesOnFontServer() // Also used in qfont_s60.cpp -{ - QStringList result; - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const int numTypeFaces = S60->screenDevice()->NumTypefaces(); - for (int i = 0; i < numTypeFaces; i++) { - TTypefaceSupport typefaceSupport; - S60->screenDevice()->TypefaceSupport(typefaceSupport, i); - const QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); - result.append(familyName); - } - lock.relock(); - return result; -} - -QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters, - QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort, - bool uniqueFileNames = true) -{ - QFileInfoList result; - - // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z: - QStringList driveStrings; - foreach (const QFileInfo &drive, QDir::drives()) - driveStrings.append(drive.absolutePath()); - driveStrings.sort(); - const QString zDriveString(QLatin1String("Z:/")); - driveStrings.removeAll(zDriveString); - driveStrings.prepend(zDriveString); - - QStringList uniqueFileNameList; - for (int i = driveStrings.count() - 1; i >= 0; --i) { - const QDir dirOnDrive(driveStrings.at(i) + path); - const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort); - if (uniqueFileNames) { - foreach(const QFileInfo &entry, entriesOnDrive) { - if (!uniqueFileNameList.contains(entry.fileName())) { - uniqueFileNameList.append(entry.fileName()); - result.append(entry); - } - } - } else { - result.append(entriesOnDrive); - } - } - return result; -} - -#ifdef QT_NO_FREETYPE -class QSymbianFontDatabaseExtrasImplementation : public QSymbianFontDatabaseExtras -{ -public: - QSymbianFontDatabaseExtrasImplementation(); - ~QSymbianFontDatabaseExtrasImplementation(); - - const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const; - void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt); - static inline bool appFontLimitReached(); - TUid addFontFileToFontStore(const QFileInfo &fontFileInfo); - static void clear(); - - static inline QString tempAppFontFolder(); - static const QString appFontMarkerPrefix; - static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>' - - struct CFontFromFontStoreReleaser { - static inline void cleanup(CFont *font) - { - if (!font) - return; - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras); - dbExtras->m_store->ReleaseFont(font); - } - }; - - struct CFontFromScreenDeviceReleaser { - static inline void cleanup(CFont *font) - { - if (!font) - return; - S60->screenDevice()->ReleaseFont(font); - } - }; - -// m_heap, m_store, m_rasterizer and m_extras are used if Symbian -// does not provide the Font Table API - RHeap* m_heap; - CFontStore *m_store; - COpenFontRasterizer *m_rasterizer; - mutable QList<const QSymbianTypeFaceExtras *> m_extras; - - mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash; - mutable QSet<QString> m_applicationFontFamilies; -}; - -const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix = - QLatin1String("Q"); - -inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() -{ - return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\'); -} - -QString QSymbianFontDatabaseExtrasImplementation::appFontMarker() -{ - static QString result; - if (result.isEmpty()) { - quint16 id = 0; - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - // We are allowed to load app fonts even from previous, crashed runs - // of this application, since we can access the font tables. - const quint32 uid = RProcess().Type().MostDerived().iUid; - id = static_cast<quint16>(uid + (uid >> 16)); - } else { - // If no font table Api is available, we must not even load a font - // from a previous (crashed) run of this application. Reason: we - // won't get the font tables, they are not in the CFontStore. - // So, we use the pid, for more uniqueness. - id = static_cast<quint16>(RProcess().Id().Id()); - } - result = appFontMarkerPrefix + QString::fromLatin1("%1").arg(id & 0x7fff, 3, 32, QLatin1Char('0')); - Q_ASSERT(appFontMarkerPrefix.length() == 1 && result.length() == 4); - } - return result; -} - -static inline bool qt_symbian_fontNameHasAppFontMarker(const QString &fontName) -{ - const int idLength = 3; // Keep in sync with id length in appFontMarker(). - const QString &prefix = QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix; - if (fontName.length() < prefix.length() + idLength - || fontName.mid(fontName.length() - idLength - prefix.length(), prefix.length()) != prefix) - return false; - // Testing if the the id is base32 data - for (int i = fontName.length() - idLength; i < fontName.length(); ++i) { - const QChar &c = fontName.at(i); - if (!(c >= QLatin1Char('0') && c <= QLatin1Char('9') - || c >= QLatin1Char('a') && c <= QLatin1Char('v'))) - return false; - } - return true; -} - -// If fontName is an application font of this app, prepend the app font marker -QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName) -{ - QFontDatabasePrivate *db = privateDb(); - Q_ASSERT(db); - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - return dbExtras->m_applicationFontFamilies.contains(fontName) ? - fontName + QSymbianFontDatabaseExtrasImplementation::appFontMarker() - : fontName; -} - -static inline QString qt_symbian_appFontNameWithoutMarker(const QString &markedFontName) -{ - return markedFontName.left(markedFontName.length() - - QSymbianFontDatabaseExtrasImplementation::appFontMarker().length()); -} - -QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation() -{ - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - QStringList filters; - filters.append(QLatin1String("*.ttf")); - filters.append(QLatin1String("*.ccc")); - filters.append(QLatin1String("*.ltt")); - const QFileInfoList fontFiles = alternativeFilePaths(QLatin1String("resource\\Fonts"), filters); - - const TInt heapMinLength = 0x1000; - const TInt heapMaxLength = qMax(0x20000 * fontFiles.count(), heapMinLength); - m_heap = User::ChunkHeap(NULL, heapMinLength, heapMaxLength); - QT_TRAP_THROWING( - m_store = CFontStore::NewL(m_heap); - m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); - CleanupStack::PushL(m_rasterizer); - m_store->InstallRasterizerL(m_rasterizer); - CleanupStack::Pop(m_rasterizer);); - - foreach (const QFileInfo &fontFileInfo, fontFiles) - addFontFileToFontStore(fontFileInfo); - } -} - -void QSymbianFontDatabaseExtrasImplementation::clear() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return; // initializeDb() has never been called - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - qDeleteAll(dbExtras->m_extrasHash); - } else { - typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator; - for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) { - dbExtras->m_store->ReleaseFont((*p)->fontOwner()); - delete *p; - } - dbExtras->m_extras.clear(); - } - dbExtras->m_extrasHash.clear(); -} - -void qt_cleanup_symbianFontDatabase() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - - QSymbianFontDatabaseExtrasImplementation::clear(); - - if (!db->applicationFonts.isEmpty()) { - QFontDatabase::removeAllApplicationFonts(); - // We remove the left over temporary font files of Qt application. - // Active fonts are undeletable since the font server holds a handle - // on them, so we do not need to worry to delete other running - // applications' fonts. - const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()); - const QStringList filter( - QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf")); - foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter)) - QFile(ttfFile.absoluteFilePath()).remove(); - db->applicationFonts.clear(); - } -} - -QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation() -{ - qt_cleanup_symbianFontDatabase(); - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - delete m_store; - m_heap->Close(); - } -} - -#ifndef FNTSTORE_H_INLINES_SUPPORT_FMM -/* - Workaround: fntstore.h has an inlined function 'COpenFont* CBitmapFont::OpenFont()' - that returns a private data member. The header will change between SDKs. But Qt has - to build on any SDK version and run on other versions of Symbian OS. - This function performs the needed pointer arithmetic to get the right COpenFont* -*/ -COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont) -{ - const TInt offsetIOpenFont = 92; // '_FOFF(CBitmapFont, iOpenFont)' ..if iOpenFont weren't private - const TUint valueIOpenFont = *(TUint*)PtrAdd(aBitmapFont, offsetIOpenFont); - return (valueIOpenFont & 1) ? - (COpenFont*)PtrAdd(aBitmapFont, valueIOpenFont & ~1) : // New behavior: iOpenFont is offset - (COpenFont*)valueIOpenFont; // Old behavior: iOpenFont is pointer -} -#endif // FNTSTORE_H_INLINES_SUPPORT_FMM - -const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface, - bool bold, bool italic) const -{ - const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface); - const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic)); - if (!m_extrasHash.contains(searchKey)) { - TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1); - if (bold) - searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold); - if (italic) - searchSpec.iFontStyle.SetPosture(EPostureItalic); - - CFont* font = NULL; - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec); - Q_ASSERT(err == KErrNone && font); - QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font); - QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font); - sFont.take(); - m_extrasHash.insert(searchKey, extras); - } else { - const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec); - Q_ASSERT(err == KErrNone && font); - const CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font); - COpenFont *openFont = -#ifdef FNTSTORE_H_INLINES_SUPPORT_FMM - bitmapFont->OpenFont(); -#else // FNTSTORE_H_INLINES_SUPPORT_FMM - OpenFontFromBitmapFont(bitmapFont); -#endif // FNTSTORE_H_INLINES_SUPPORT_FMM - const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib(); - const QString foundKey = - QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length()); - if (!m_extrasHash.contains(foundKey)) { - QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font); - QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont); - sFont.take(); - m_extras.append(extras); - m_extrasHash.insert(searchKey, extras); - m_extrasHash.insert(foundKey, extras); - } else { - m_store->ReleaseFont(font); - m_extrasHash.insert(searchKey, m_extrasHash.value(foundKey)); - } - } - } - return m_extrasHash.value(searchKey); -} - -void QSymbianFontDatabaseExtrasImplementation::removeAppFontData( - QFontDatabasePrivate::ApplicationFont *fnt) -{ - clear(); - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable() - && fnt->fontStoreFontFileUid.iUid != 0) - m_store->RemoveFile(fnt->fontStoreFontFileUid); - if (!fnt->families.isEmpty()) - m_applicationFontFamilies.remove(fnt->families.first()); - if (fnt->screenDeviceFontFileId != 0) - S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); - QFile::remove(fnt->temporaryFileName); - *fnt = QFontDatabasePrivate::ApplicationFont(); -} - -bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db) - return false; - const int maxAppFonts = 5; - int registeredAppFonts = 0; - foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts) - if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts) - return true; - return false; -} - -TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo) -{ - Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()); - const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); - const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); - TUid fontUid = {0}; - TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr)); - return fontUid; -} - -#else // QT_NO_FREETYPE -class QFontEngineFTS60 : public QFontEngineFT -{ -public: - QFontEngineFTS60(const QFontDef &fd); -}; - -QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd) - : QFontEngineFT(fd) -{ - default_hint_style = HintFull; -} -#endif // QT_NO_FREETYPE - -/* - QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60 - and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the - Freetype based font rendering need them, they are here. -*/ -qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) -{ - CWsScreenDevice* device = S60->screenDevice(); - return (orientation == Qt::Horizontal? - device->HorizontalPixelsToTwips(pixels) - :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; -} - -qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) -{ - CWsScreenDevice* device = S60->screenDevice(); - const int twips = points * KTwipsPerPoint; - return orientation == Qt::Horizontal? - device->HorizontalTwipsToPixels(twips) - :device->VerticalTwipsToPixels(twips); -} - -QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies) - : QFontEngineMulti(fallbackFamilies.size() + 1) - , m_script(script) - , m_fallbackFamilies(fallbackFamilies) -{ - engines[0] = first; - first->ref.ref(); - fontDef = engines[0]->fontDef; -} - -void QFontEngineMultiS60::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - QFontDef request = fontDef; - request.styleStrategy |= QFont::NoFontMerging; - request.family = m_fallbackFamilies.at(at-1); - engines[at] = QFontDatabase::findFont(m_script, - /*fontprivate*/0, - request); - Q_ASSERT(engines[at]); -} - -#ifdef QT_NO_FREETYPE -static bool registerScreenDeviceFont(int screenDeviceFontIndex, - const QSymbianFontDatabaseExtrasImplementation *dbExtras) -{ - TTypefaceSupport typefaceSupport; - S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex); - - QString familyName((const QChar*)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); - if (qt_symbian_fontNameHasAppFontMarker(familyName)) { - const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); - if (familyName.endsWith(marker)) { - familyName = qt_symbian_appFontNameWithoutMarker(familyName); - dbExtras->m_applicationFontFamilies.insert(familyName); - } else { - return false; // This was somebody else's application font. Skip it. - } - } - - CFont *font; // We have to get a font instance in order to know all the details - TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); - if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) - return false; - QScopedPointer<CFont, QSymbianFontDatabaseExtrasImplementation::CFontFromScreenDeviceReleaser> sFont(font); - if (font->TypeUid() != KCFbsFontUid) - return false; - TOpenFontFaceAttrib faceAttrib; - const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font); - cfbsFont->GetFaceAttrib(faceAttrib); - - QtFontStyle::Key styleKey; - styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; - styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; - - QtFontFamily *family = privateDb()->family(familyName, true); - family->fixedPitch = faceAttrib.IsMonoWidth(); - QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = typefaceSupport.iIsScalable; - style->pixelSize(0, true); - - const QSymbianTypeFaceExtras *typeFaceExtras = - dbExtras->extras(familyName, faceAttrib.IsBold(), faceAttrib.IsItalic()); - const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); - const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); - const unsigned char* ulUnicodeRange = data + 42; - quint32 unicodeRange[4] = { - qFromBigEndian<quint32>(ulUnicodeRange), - qFromBigEndian<quint32>(ulUnicodeRange + 4), - qFromBigEndian<quint32>(ulUnicodeRange + 8), - qFromBigEndian<quint32>(ulUnicodeRange + 12) - }; - const unsigned char* ulCodePageRange = data + 78; - quint32 codePageRange[2] = { - qFromBigEndian<quint32>(ulCodePageRange), - qFromBigEndian<quint32>(ulCodePageRange + 4) - }; - const QList<QFontDatabase::WritingSystem> writingSystems = - qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); - foreach (const QFontDatabase::WritingSystem system, writingSystems) - family->writingSystems[system] = QtFontFamily::Supported; - return true; -} -#endif - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if(!db || db->count) - return; - -#ifdef QT_NO_FREETYPE - if (!db->symbianExtras) - db->symbianExtras = new QSymbianFontDatabaseExtrasImplementation; - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - const int numTypeFaces = S60->screenDevice()->NumTypefaces(); - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - for (int i = 0; i < numTypeFaces; i++) - registerScreenDeviceFont(i, dbExtras); - - // We have to clear/release all CFonts, here, in case one of the fonts is - // an application font of another running Qt app. Otherwise the other Qt app - // cannot remove it's application font, anymore -> "Zombie Font". - QSymbianFontDatabaseExtrasImplementation::clear(); - - lock.relock(); - -#else // QT_NO_FREETYPE - QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation)); - dir.setNameFilters(QStringList() << QLatin1String("*.ttf") - << QLatin1String("*.ttc") << QLatin1String("*.pfa") - << QLatin1String("*.pfb")); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); - db->addTTFile(file); - } -#endif // QT_NO_FREETYPE -} - -static inline void load(const QString &family = QString(), int script = -1) -{ - Q_UNUSED(family) - Q_UNUSED(script) - initializeDb(); -} - -struct OffsetTable { - quint32 sfntVersion; - quint16 numTables, searchRange, entrySelector, rangeShift; -}; - -struct TableRecord { - quint32 tag, checkSum, offset, length; -}; - -struct NameTableHead { - quint16 format, count, stringOffset; -}; - -struct NameRecord { - quint16 platformID, encodingID, languageID, nameID, length, offset; -}; - -static quint32 ttfCalcChecksum(const char *data, quint32 bytesCount) -{ - quint32 result = 0; - const quint32 *ptr = reinterpret_cast<const quint32*>(data); - const quint32 *endPtr = - ptr + (bytesCount + sizeof(quint32) - 1) / sizeof(quint32); - while (ptr < endPtr) { - const quint32 unit32Value = *ptr++; - result += qFromBigEndian(unit32Value); - } - return result; -} - -static inline quint32 toDWordBoundary(quint32 value) -{ - return (value + 3) & ~3; -} - -static inline quint32 dWordPadding(quint32 value) -{ - return (4 - (value & 3)) & 3; -} - -static inline bool ttfMarkNameTable(QByteArray &table, const QString &marker) -{ - const quint32 tableLength = static_cast<quint32>(table.size()); - - if (tableLength > 50000 // hard limit - || tableLength < sizeof(NameTableHead)) // corrupt name table - return false; - - const NameTableHead *head = reinterpret_cast<const NameTableHead*>(table.constData()); - const quint16 count = qFromBigEndian(head->count); - const quint16 stringOffset = qFromBigEndian(head->stringOffset); - if (count > 200 // hard limit - || stringOffset >= tableLength // corrupt name table - || sizeof(NameTableHead) + count * sizeof(NameRecord) >= tableLength) // corrupt name table - return false; - - QTextEncoder encoder(QTextCodec::codecForName("UTF-16BE"), QTextCodec::IgnoreHeader); - const QByteArray markerUtf16BE = encoder.fromUnicode(marker); - const QByteArray markerAscii = marker.toAscii(); - - QByteArray markedTable; - markedTable.reserve(tableLength + marker.length() * 20); // Original size plus some extra - markedTable.append(table, stringOffset); - QByteArray markedStrings; - quint32 stringDataCount = stringOffset; - for (quint16 i = 0; i < count; ++i) { - const quint32 nameRecordOffset = sizeof(NameTableHead) + sizeof(NameRecord) * i; - NameRecord *nameRecord = - reinterpret_cast<NameRecord*>(markedTable.data() + nameRecordOffset); - const quint16 nameID = qFromBigEndian(nameRecord->nameID); - const quint16 platformID = qFromBigEndian(nameRecord->platformID); - const quint16 encodingID = qFromBigEndian(nameRecord->encodingID); - const quint16 offset = qFromBigEndian(nameRecord->offset); - const quint16 length = qFromBigEndian(nameRecord->length); - stringDataCount += length; - if (stringDataCount > 80000 // hard limit. String data may be > name table size. Multiple records can reference the same string. - || static_cast<quint32>(stringOffset + offset + length) > tableLength) // String outside bounds - return false; - const bool needsMarker = - nameID == 1 || nameID == 3 || nameID == 4 || nameID == 16 || nameID == 21; - const bool isUnicode = - platformID == 0 || platformID == 3 && encodingID == 1; - const QByteArray originalString = - QByteArray::fromRawData(table.constData() + stringOffset + offset, length); - QByteArray markedString; - if (needsMarker) { - const int maxBytesLength = (KMaxTypefaceNameLength - marker.length()) * (isUnicode ? 2 : 1); - markedString = originalString.left(maxBytesLength) + (isUnicode ? markerUtf16BE : markerAscii); - } else { - markedString = originalString; - } - nameRecord->offset = qToBigEndian(static_cast<quint16>(markedStrings.length())); - nameRecord->length = qToBigEndian(static_cast<quint16>(markedString.length())); - markedStrings.append(markedString); - } - markedTable.append(markedStrings); - table = markedTable; - return true; -} - -const quint32 ttfMaxFileSize = 3500000; - -static inline bool ttfMarkAppFont(QByteArray &ttf, const QString &marker) -{ - const quint32 ttfChecksumNumber = 0xb1b0afba; - const quint32 alignment = 4; - const quint32 ttfLength = static_cast<quint32>(ttf.size()); - if (ttfLength > ttfMaxFileSize // hard limit - || ttfLength % alignment != 0 // ttf sizes are always factors of 4 - || ttfLength <= sizeof(OffsetTable) // ttf too short - || ttfCalcChecksum(ttf.constData(), ttf.size()) != ttfChecksumNumber) // ttf checksum is invalid - return false; - - const OffsetTable *offsetTable = reinterpret_cast<const OffsetTable*>(ttf.constData()); - const quint16 numTables = qFromBigEndian(offsetTable->numTables); - const quint32 recordsLength = - toDWordBoundary(sizeof(OffsetTable) + numTables * sizeof(TableRecord)); - if (numTables > 30 // hard limit - || recordsLength + numTables * alignment > ttfLength) // Corrupt ttf. Tables would not fit, even if empty. - return false; - - QByteArray markedTtf; - markedTtf.reserve(ttfLength + marker.length() * 20); // Original size plus some extra - markedTtf.append(ttf.constData(), recordsLength); - - const quint32 ttfCheckSumAdjustmentOffset = 8; // Offset from the start of 'head' - int indexOfHeadTable = -1; - quint32 ttfDataSize = recordsLength; - typedef QPair<quint32, quint32> Range; - QList<Range> memoryRanges; - memoryRanges.reserve(numTables); - for (int i = 0; i < numTables; ++i) { - TableRecord *tableRecord = - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); - const quint32 offset = qFromBigEndian(tableRecord->offset); - const quint32 length = qFromBigEndian(tableRecord->length); - const quint32 lengthAligned = toDWordBoundary(length); - ttfDataSize += lengthAligned; - if (offset < recordsLength // must not intersect ttf header/records - || offset % alignment != 0 // must be aligned - || offset > ttfLength - alignment // table out of bounds - || offset + lengthAligned > ttfLength // table out of bounds - || ttfDataSize > ttfLength) // tables would not fit into the ttf - return false; - - foreach (const Range &range, memoryRanges) - if (offset < range.first + range.second && offset + lengthAligned > range.first) - return false; // Overlaps with another table - memoryRanges.append(Range(offset, lengthAligned)); - - quint32 checkSum = qFromBigEndian(tableRecord->checkSum); - if (tableRecord->tag == qToBigEndian(static_cast<quint32>('head'))) { - if (length < ttfCheckSumAdjustmentOffset + sizeof(quint32)) - return false; // Invalid 'head' table - const quint32 *checkSumAdjustmentTag = - reinterpret_cast<const quint32*>(ttf.constData() + offset + ttfCheckSumAdjustmentOffset); - const quint32 checkSumAdjustment = qFromBigEndian(*checkSumAdjustmentTag); - checkSum += checkSumAdjustment; - indexOfHeadTable = i; // For the ttf checksum re-calculation, later - } - if (checkSum != ttfCalcChecksum(ttf.constData() + offset, length)) - return false; // Table checksum is invalid - - bool updateTableChecksum = false; - QByteArray table; - if (tableRecord->tag == qToBigEndian(static_cast<quint32>('name'))) { - table = QByteArray(ttf.constData() + offset, length); - if (!ttfMarkNameTable(table, marker)) - return false; // Name table was not markable. - updateTableChecksum = true; - } else { - table = QByteArray::fromRawData(ttf.constData() + offset, length); - } - - tableRecord->offset = qToBigEndian(markedTtf.size()); - tableRecord->length = qToBigEndian(table.size()); - markedTtf.append(table); - markedTtf.append(QByteArray(dWordPadding(table.size()), 0)); // 0-padding - if (updateTableChecksum) { - TableRecord *tableRecord = // Need to recalculate, since markedTtf changed - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); - const quint32 offset = qFromBigEndian(tableRecord->offset); - const quint32 length = qFromBigEndian(tableRecord->length); - tableRecord->checkSum = qToBigEndian(ttfCalcChecksum(markedTtf.constData() + offset, length)); - } - } - if (indexOfHeadTable == -1 // 'head' table is mandatory - || ttfDataSize != ttfLength) // We do not allow ttf data "holes". Neither does Symbian. - return false; - TableRecord *headRecord = - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + indexOfHeadTable * sizeof(TableRecord)); - quint32 *checkSumAdjustmentTag = - reinterpret_cast<quint32*>(markedTtf.data() + qFromBigEndian(headRecord->offset) + ttfCheckSumAdjustmentOffset); - *checkSumAdjustmentTag = 0; - const quint32 ttfChecksum = ttfCalcChecksum(markedTtf.constData(), markedTtf.count()); - *checkSumAdjustmentTag = qToBigEndian(ttfChecksumNumber - ttfChecksum); - ttf = markedTtf; - return true; -} - -static inline bool ttfCanSymbianLoadFont(const QByteArray &data, const QString &fileName) -{ - bool result = false; - QString ttfFileName; - QFile tempFileGuard; - QFileInfo info(fileName); - if (!data.isEmpty()) { - QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() - + QSymbianFontDatabaseExtrasImplementation::appFontMarker() - + QLatin1String("XXXXXX.ttf")); - if (!tempfile.open() || tempfile.write(data) == -1) - return false; - ttfFileName = QDir::toNativeSeparators(QFileInfo(tempfile).canonicalFilePath()); - tempfile.setAutoRemove(false); - tempfile.close(); - tempFileGuard.setFileName(ttfFileName); - if (!tempFileGuard.open(QIODevice::ReadOnly)) - return false; - } else if (info.isFile()) { - ttfFileName = QDir::toNativeSeparators(info.canonicalFilePath()); - } else { - return false; - } - - CFontStore *store = 0; - RHeap* heap = User::ChunkHeap(NULL, 0x1000, 0x20000); - if (heap) { - QT_TRAP_THROWING( - CleanupClosePushL(*heap); - store = CFontStore::NewL(heap); - CleanupStack::PushL(store); - COpenFontRasterizer *rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); - CleanupStack::PushL(rasterizer); - store->InstallRasterizerL(rasterizer); - CleanupStack::Pop(rasterizer); - TUid fontUid = {-1}; - TRAP_IGNORE(fontUid = store->AddFileL(qt_QString2TPtrC(ttfFileName))); - if (fontUid.iUid != -1) - result = true; - CleanupStack::PopAndDestroy(2, heap); // heap, store - ); - } - - if (tempFileGuard.isOpen()) - tempFileGuard.remove(); - - return result; -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() - || fnt->data.size() > ttfMaxFileSize // hard limit - || fnt->data.isEmpty() && (!fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) // Only buffer or .ttf - || QFileInfo(fnt->fileName).size() > ttfMaxFileSize)) // hard limit - return; - -// Using ttfCanSymbianLoadFont() causes crashes on app destruction (Symbian^3|PR1 and lower). -// Therefore, not using it for now, but eventually in a later version. -// if (!ttfCanSymbianLoadFont(fnt->data, fnt->fileName)) -// return; - - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - - if (!db->count) - initializeDb(); - - QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return; - - const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); - - // The QTemporaryFile object being used in the following section must be - // destructed before letting Symbian load the TTF file. Symbian would not - // load it otherwise, because QTemporaryFile will still keep some handle - // on it. The scope is used to reduce the life time of the QTemporaryFile. - // In order to prevent other processes from modifying the file between the - // moment where the QTemporaryFile is destructed and the file is loaded by - // Symbian, we have a QFile "tempFileGuard" outside the scope which opens - // the file in ReadOnly mode while the QTemporaryFile is still alive. - QFile tempFileGuard; - { - QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() - + marker + QLatin1String("XXXXXX.ttf")); - if (!tempfile.open()) - return; - const QString tempFileName = QFileInfo(tempfile).canonicalFilePath(); - if (fnt->data.isEmpty()) { - QFile sourceFile(fnt->fileName); - if (!sourceFile.open(QIODevice::ReadOnly)) - return; - fnt->data = sourceFile.readAll(); - } - if (!ttfMarkAppFont(fnt->data, marker) || tempfile.write(fnt->data) == -1) - return; - tempfile.setAutoRemove(false); - tempfile.close(); // Tempfile still keeps a file handle, forbidding write access - fnt->data.clear(); // The TTF data was marked and saved. Not needed in memory, anymore. - tempFileGuard.setFileName(tempFileName); - if (!tempFileGuard.open(QIODevice::ReadOnly)) - return; - fnt->temporaryFileName = tempFileName; - } - - const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName); - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer(); - const TInt err = - S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId); - tempFileGuard.close(); // Did its job - const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer(); - if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device? - int fontOnServerIndex = fontsOnServerAfter.count() - 1; - for (int i = 0; i < fontsOnServerBefore.count(); i++) { - if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) { - fontOnServerIndex = i; - break; - } - } - - // Must remove all font engines with their CFonts, first. - QFontCache::instance()->clear(); - db->free(); - QSymbianFontDatabaseExtrasImplementation::clear(); - - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) - fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName)); - - const QString &appFontName = fontsOnServerAfter.at(fontOnServerIndex); - fnt->families.append(qt_symbian_appFontNameWithoutMarker(appFontName)); - if (!qt_symbian_fontNameHasAppFontMarker(appFontName) - || !registerScreenDeviceFont(fontOnServerIndex, dbExtras)) - dbExtras->removeAppFontData(fnt); - } else { - if (fnt->screenDeviceFontFileId > 0) - S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); // May still have the file open! - QFile::remove(fnt->temporaryFileName); - *fnt = QFontDatabasePrivate::ApplicationFont(); - } - lock.relock(); -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (!db || handle < 0 || handle >= db->applicationFonts.count()) - return false; - QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return false; - - QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle]; - if (fnt->families.isEmpty()) - return true; // Nothing to remove. Return peacefully. - - // Must remove all font engines with their CFonts, first - QFontCache::instance()->clear(); - db->free(); - dbExtras->removeAppFontData(fnt); - - db->invalidate(); // This will just emit 'fontDatabaseChanged()' - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - const int applicationFontsCount = privateDb()->applicationFonts.count(); - for (int i = 0; i < applicationFontsCount; ++i) - if (!removeApplicationFont(i)) - return false; - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return false; -} - -static -QFontDef cleanedFontDef(const QFontDef &req) -{ - QFontDef result = req; - if (result.pixelSize <= 0) { - result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize)); - result.pointSize = 0; - } - return result; -} - -QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QFontDef &req) -{ - const QFontCache::Key key(cleanedFontDef(req), script); - - if (!privateDb()->count) - initializeDb(); - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - if (!fe) { - // Making sure that fe->fontDef.family will be an existing font. - initializeDb(); - QFontDatabasePrivate *db = privateDb(); - QtFontDesc desc; - QList<int> blacklistedFamilies; - match(script, key.def, key.def.family, QString(), -1, &desc, blacklistedFamilies); - if (!desc.family) // falling back to application font - desc.family = db->family(QApplication::font().defaultFamily()); - Q_ASSERT(desc.family); - - // Making sure that desc.family supports the requested script - QtFontDesc mappedDesc; - bool supportsScript = false; - do { - match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); - if (mappedDesc.family == desc.family) { - supportsScript = true; - break; - } - blacklistedFamilies.append(mappedDesc.familyIndex); - } while (mappedDesc.family); - if (!supportsScript) { - blacklistedFamilies.clear(); - match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); - if (mappedDesc.family) - desc = mappedDesc; - } - - const QString fontFamily = desc.family->name; - QFontDef request = req; - request.family = fontFamily; -#ifdef QT_NO_FREETYPE - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - const QSymbianTypeFaceExtras *typeFaceExtras = - dbExtras->extras(fontFamily, request.weight > QFont::Normal, request.style != QFont::StyleNormal); - - // We need a valid pixelSize, e.g. for lineThickness() - if (request.pixelSize < 0) - request.pixelSize = request.pointSize * d->dpi / 72; - - fe = new QFontEngineS60(request, typeFaceExtras); -#else // QT_NO_FREETYPE - Q_UNUSED(d) - QFontEngine::FaceId faceId; - const QtFontFamily * const reqQtFontFamily = db->family(fontFamily); - faceId.filename = reqQtFontFamily->fontFilename; - faceId.index = reqQtFontFamily->fontFileIndex; - - QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request)); - if (fte->init(faceId, true, QFontEngineFT::Format_A8)) - fe = fte; - else - delete fte; -#endif // QT_NO_FREETYPE - - Q_ASSERT(fe); - if (script == QUnicodeTables::Common - && !(req.styleStrategy & QFont::NoFontMerging) - && !fe->symbol) { - - QStringList commonFonts; - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - if (scriptForWritingSystem[ws] != script) - continue; - for (int i = 0; i < db->count; ++i) { - if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported) - commonFonts.append(db->families[i]->name); - } - } - - // Hack: Prioritize .ccc fonts - const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60")); - if (commonFonts.removeAll(niceEastAsianFont) > 0) - commonFonts.prepend(niceEastAsianFont); - - fe = new QFontEngineMultiS60(fe, script, commonFonts); - } - } - fe->ref.ref(); - QFontCache::instance()->insertEngine(key, fe); - return fe; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - QFontEngine *fe = 0; - QFontDef req = d->request; - - if (!d->engineData) { - const QFontCache::Key key(cleanedFontDef(req), script); - getEngineData(d, key); - } - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) - fe = d->engineData->engines[script]; - - if (!fe) { - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else { - fe = findFont(script, d, req); - } - d->engineData->engines[script] = fe; - } -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qfontengine_s60.cpp b/src/gui/platforms/s60/qfontengine_s60.cpp deleted file mode 100644 index e9b54e350f..0000000000 --- a/src/gui/platforms/s60/qfontengine_s60.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_s60_p.h" -#include "qtextengine_p.h" -#include "qendian.h" -#include "qglobal.h" -#include <private/qapplication_p.h> -#include "qimage.h" -#include <private/qt_s60_p.h> -#include <private/qpixmap_s60_p.h> - -#include <e32base.h> -#include <e32std.h> -#include <eikenv.h> -#include <gdi.h> -#if defined(Q_SYMBIAN_HAS_GLYPHOUTLINE_API) -#include <graphics/gdi/gdiplatapi.h> -#endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -// Replication of TGetFontTableParam & friends. -// There is unfortunately no compile time flag like SYMBIAN_FONT_TABLE_API -// that would help us to only replicate these things for Symbian versions -// that do not yet have the font table Api. Symbian's public SDK does -// generally not define any usable macros. -class QSymbianTGetFontTableParam -{ -public: - TUint32 iTag; - TAny *iContent; - TInt iLength; -}; -const TUid QSymbianKFontGetFontTable = {0x102872C1}; -const TUid QSymbianKFontReleaseFontTable = {0x2002AC24}; - -QT_BEGIN_NAMESPACE - -QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont) - : m_cFont(cFont) - , m_symbolCMap(false) - , m_openFont(openFont) -{ - if (!symbianFontTableApiAvailable()) { - TAny *trueTypeExtension = NULL; - m_openFont->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension); - m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension); - Q_ASSERT(m_trueTypeExtension); - } -} - -QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras() -{ - if (symbianFontTableApiAvailable()) - S60->screenDevice()->ReleaseFont(m_cFont); -} - -QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const -{ - if (symbianFontTableApiAvailable()) { - QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; - if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - const char* const fontTableContent = - static_cast<const char *>(fontTableParams.iContent); - const QByteArray fontTable(fontTableContent, fontTableParams.iLength); - m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - return fontTable; - } - return QByteArray(); - } else { - Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); - TInt error = KErrNone; - TInt tableByteLength = 0; - TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); - Q_CHECK_PTR(table); - const QByteArray result(static_cast<const char*>(table), tableByteLength); - m_trueTypeExtension->ReleaseTrueTypeTable(table); - return result; - } -} - -bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - bool result = true; - if (symbianFontTableApiAvailable()) { - QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; - if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - if (*length > 0 && *length < fontTableParams.iLength) { - result = false; // Caller did not allocate enough memory - } else { - *length = fontTableParams.iLength; - if (buffer) - memcpy(buffer, fontTableParams.iContent, fontTableParams.iLength); - } - m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - } else { - result = false; - } - } else { - if (!m_trueTypeExtension->HasTrueTypeTable(tag)) - return false; - - TInt error = KErrNone; - TInt tableByteLength; - TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); - Q_CHECK_PTR(table); - - if (error != KErrNone) { - return false; - } else if (*length > 0 && *length < tableByteLength) { - result = false; // Caller did not allocate enough memory - } else { - *length = tableByteLength; - if (buffer) - memcpy(buffer, table, tableByteLength); - } - - m_trueTypeExtension->ReleaseTrueTypeTable(table); - } - return result; -} - -const uchar *QSymbianTypeFaceExtras::cmap() const -{ - if (m_cmapTable.isNull()) { - const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); - int size = 0; - const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *> - (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size); - m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size); - } - return reinterpret_cast<const uchar *>(m_cmapTable.constData()); -} - -bool QSymbianTypeFaceExtras::isSymbolCMap() const -{ - return m_symbolCMap; -} - -CFont *QSymbianTypeFaceExtras::fontOwner() const -{ - return m_cFont; -} - -QFixed QSymbianTypeFaceExtras::unitsPerEm() const -{ - if (m_unitsPerEm.value() != 0) - return m_unitsPerEm; - const QByteArray head = getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); - const int unitsPerEmOffset = 18; - if (head.size() > unitsPerEmOffset + sizeof(quint16)) { - const uchar* tableData = reinterpret_cast<const uchar*>(head.constData()); - const uchar* unitsPerEm = tableData + unitsPerEmOffset; - m_unitsPerEm = qFromBigEndian<quint16>(unitsPerEm); - } else { - // Bitmap font? Corrupt font? - // We return -1 and let the QFontEngineS60 return the pixel size. - m_unitsPerEm = -1; - } - return m_unitsPerEm; -} - -bool QSymbianTypeFaceExtras::symbianFontTableApiAvailable() -{ - enum FontTableApiAvailability { - Unknown, - Available, - Unavailable - }; - static FontTableApiAvailability availability = - QSysInfo::symbianVersion() < QSysInfo::SV_SF_3 ? - Unavailable : Unknown; - if (availability == Unknown) { - // Actually, we should ask CFeatureDiscovery::IsFeatureSupportedL() - // with FfFontTable here. But since at the time of writing, the - // FfFontTable flag check either gave false positives or false - // negatives. Here comes an implicit check via CFont::ExtendedFunction. - QSymbianTGetFontTableParam fontTableParams = { - MAKE_TAG('O', 'S', '/', '2'), 0, 0 }; - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - CFont *font; - const TInt getFontErr = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); - Q_ASSERT(getFontErr == KErrNone); - if (font->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - font->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - availability = Available; - } else { - availability = Unavailable; - } - S60->screenDevice()->ReleaseFont(font); - lock.relock(); - } - return availability == Available; -} - -// duplicated from qfontengine_xyz.cpp -static inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -extern QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName); // qfontdatabase_s60.cpp - -CFont *QFontEngineS60::fontWithSize(qreal size) const -{ - CFont *result = 0; - const QString family = qt_symbian_fontNameWithAppFontMarker(QFontEngine::fontDef.family); - TFontSpec fontSpec(qt_QString2TPtrC(family), TInt(size)); - fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); - fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); - fontSpec.iFontStyle.SetStrokeWeight(QFontEngine::fontDef.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); - const TInt errorCode = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(result, fontSpec); - Q_ASSERT(result && (errorCode == 0)); - return result; -} - -void QFontEngineS60::setFontScale(qreal scale) -{ - if (qFuzzyCompare(scale, qreal(1))) { - if (!m_originalFont) - m_originalFont = fontWithSize(m_originalFontSizeInPixels); - m_activeFont = m_originalFont; - } else { - const qreal scaledFontSizeInPixels = m_originalFontSizeInPixels * scale; - if (!m_scaledFont || - (TInt(scaledFontSizeInPixels) != TInt(m_scaledFontSizeInPixels))) { - releaseFont(m_scaledFont); - m_scaledFontSizeInPixels = scaledFontSizeInPixels; - m_scaledFont = fontWithSize(m_scaledFontSizeInPixels); - } - m_activeFont = m_scaledFont; - } -} - -void QFontEngineS60::releaseFont(CFont *&font) -{ - if (font) { - S60->screenDevice()->ReleaseFont(font); - font = 0; - } -} - -QFontEngineS60::QFontEngineS60(const QFontDef &request, const QSymbianTypeFaceExtras *extras) - : m_extras(extras) - , m_originalFont(0) - , m_originalFontSizeInPixels((request.pixelSize >= 0)? - request.pixelSize:pointsToPixels(request.pointSize)) - , m_scaledFont(0) - , m_scaledFontSizeInPixels(0) - , m_activeFont(0) -{ - QFontEngine::fontDef = request; - setFontScale(1.0); - cache_cost = sizeof(QFontEngineS60); -} - -QFontEngineS60::~QFontEngineS60() -{ - releaseFont(m_originalFont); - releaseFont(m_scaledFont); -} - -QFixed QFontEngineS60::emSquareSize() const -{ - const QFixed unitsPerEm = m_extras->unitsPerEm(); - return unitsPerEm.toInt() == -1 ? - QFixed::fromReal(m_originalFontSizeInPixels) : unitsPerEm; -} - -bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - HB_Glyph *g = glyphs->glyphs; - const unsigned char* cmap = m_extras->cmap(); - const bool isRtl = (flags & QTextEngine::RightToLeft); - for (int i = 0; i < len; ++i) { - const unsigned int uc = getChar(characters, i, len); - *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, - (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc); - } - - glyphs->numGlyphs = g - glyphs->glyphs; - *nglyphs = glyphs->numGlyphs; - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - recalcAdvances(glyphs, flags); - return true; -} - -void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_UNUSED(flags); - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - for (int i = 0; i < glyphs->numGlyphs; i++) { - getCharacterData(glyphs->glyphs[i], metrics, glyphBitmapBytes, glyphBitmapSize); - glyphs->advances_x[i] = metrics.HorizAdvance(); - glyphs->advances_y[i] = 0; - } -} - -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API -static bool parseGlyphPathData(const char *dataStr, const char *dataEnd, QPainterPath &path, - qreal fontPixelSize, const QPointF &offset, bool hinted); -#endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, - int nglyphs, QPainterPath *path, - QTextItem::RenderFlags flags) -{ -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API - Q_UNUSED(flags) - RGlyphOutlineIterator iterator; - const TInt error = iterator.Open(*m_activeFont, glyphs, nglyphs); - if (KErrNone != error) - return; - const qreal fontSizeInPixels = qreal(m_activeFont->HeightInPixels()); - int count = 0; - do { - const TUint8* outlineUint8 = iterator.Outline(); - const char* const outlineChar = reinterpret_cast<const char*>(outlineUint8); - const char* const outlineEnd = outlineChar + iterator.OutlineLength(); - parseGlyphPathData(outlineChar, outlineEnd, *path, fontSizeInPixels, - positions[count++].toPointF(), false); - } while(KErrNone == iterator.Next() && count <= nglyphs); - iterator.Close(); -#else // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags); -#endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API -} - -QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph) -{ - // Note: On some Symbian versions (apparently <= Symbian^1), this - // function will return gray values 0x00, 0x10 ... 0xe0, 0xf0 due - // to a bug. The glyphs are nowhere perfectly opaque. - // This has been fixed for Symbian^3. - - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); - QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8); - result.setColorTable(grayPalette()); - return result; -} - -glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); -} - -glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const -{ - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); - const glyph_metrics_t result( - metrics.HorizBearingX(), - -metrics.HorizBearingY(), - metrics.Width(), - metrics.Height(), - metrics.HorizAdvance(), - 0 - ); - return result; -} - -glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph) -{ - return boundingBox_const(glyph); -} - -QFixed QFontEngineS60::ascent() const -{ - // Workaround for QTBUG-8013 - // Stroke based fonts may return an incorrect FontMaxAscent of 0. - const QFixed ascent = m_originalFont->FontMaxAscent(); - return (ascent > 0) ? ascent : QFixed::fromReal(m_originalFontSizeInPixels) - descent(); -} - -QFixed QFontEngineS60::descent() const -{ - return m_originalFont->FontMaxDescent(); -} - -QFixed QFontEngineS60::leading() const -{ - return 0; -} - -qreal QFontEngineS60::maxCharWidth() const -{ - return m_originalFont->MaxCharWidthInPixels(); -} - -const char *QFontEngineS60::name() const -{ - return "QFontEngineS60"; -} - -bool QFontEngineS60::canRender(const QChar *string, int len) -{ - const unsigned char *cmap = m_extras->cmap(); - for (int i = 0; i < len; ++i) { - const unsigned int uc = getChar(string, i, len); - if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0) - return false; - } - return true; -} - -QByteArray QFontEngineS60::getSfntTable(uint tag) const -{ - return m_extras->getSfntTable(tag); -} - -bool QFontEngineS60::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - return m_extras->getSfntTableData(tag, buffer, length); -} - -QFontEngine::Type QFontEngineS60::type() const -{ - return QFontEngine::S60FontEngine; -} - -void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const -{ - // Setting the most significant bit tells GetCharacterData - // that 'code' is a Glyph ID, rather than a UTF-16 value - const TUint specialCode = (TUint)glyph | 0x80000000; - - const CFont::TCharacterDataAvailability availability = - m_activeFont->GetCharacterData(specialCode, metrics, bitmap, bitmapSize); - const glyph_t fallbackGlyph = '?'; - if (availability != CFont::EAllCharacterData) { - const CFont::TCharacterDataAvailability fallbackAvailability = - m_activeFont->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize); - Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData); - } -} - -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API -static inline void skipSpacesAndComma(const char* &str, const char* const strEnd) -{ - while (str <= strEnd && (*str == ' ' || *str == ',')) - ++str; -} - -static bool parseGlyphPathData(const char *svgPath, const char *svgPathEnd, QPainterPath &path, - qreal fontPixelSize, const QPointF &offset, bool hinted) -{ - Q_UNUSED(hinted) - QPointF p1, p2, firstSubPathPoint; - qreal *elementValues[] = - {&p1.rx(), &p1.ry(), &p2.rx(), &p2.ry()}; - const int unitsPerEm = 2048; // See: http://en.wikipedia.org/wiki/Em_%28typography%29 - const qreal resizeFactor = fontPixelSize / unitsPerEm; - - while (svgPath < svgPathEnd) { - skipSpacesAndComma(svgPath, svgPathEnd); - const char pathElem = *svgPath++; - skipSpacesAndComma(svgPath, svgPathEnd); - - if (pathElem != 'Z') { - char *endStr = 0; - int elementValuesCount = 0; - for (int i = 0; i < 4; ++i) { // 4 = size of elementValues[] - qreal coordinateValue = strtod(svgPath, &endStr); - if (svgPath == endStr) - break; - if (i % 2) // Flip vertically - coordinateValue = -coordinateValue; - *elementValues[i] = coordinateValue * resizeFactor; - elementValuesCount++; - svgPath = endStr; - skipSpacesAndComma(svgPath, svgPathEnd); - } - p1 += offset; - if (elementValuesCount == 2) - p2 = firstSubPathPoint; - else - p2 += offset; - } - - switch (pathElem) { - case 'M': - firstSubPathPoint = p1; - path.moveTo(p1); - break; - case 'Z': - path.closeSubpath(); - break; - case 'L': - path.lineTo(p1); - break; - case 'Q': - path.quadTo(p1, p2); - break; - default: - return false; - } - } - return true; -} -#endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qfontengine_s60_p.h b/src/gui/platforms/s60/qfontengine_s60_p.h deleted file mode 100644 index c0eeef5264..0000000000 --- a/src/gui/platforms/s60/qfontengine_s60_p.h +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_S60_P_H -#define QFONTENGINE_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qconfig.h" -#include <private/qfontengine_p.h> -#include "qsize.h" -#include <openfont.h> - -// The glyph outline code is intentionally disabled. It will be reactivated as -// soon as the glyph outline API is backported from Symbian(^4) to Symbian(^3). -#if 0 -#define Q_SYMBIAN_HAS_GLYPHOUTLINE_API -#endif - -class CFont; - -QT_BEGIN_NAMESPACE - -// ..gives us access to truetype tables -class QSymbianTypeFaceExtras -{ -public: - QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont = 0); - ~QSymbianTypeFaceExtras(); - - QByteArray getSfntTable(uint tag) const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - const uchar *cmap() const; - CFont *fontOwner() const; - bool isSymbolCMap() const; - QFixed unitsPerEm() const; - static bool symbianFontTableApiAvailable(); - -private: - CFont* m_cFont; - mutable bool m_symbolCMap; - mutable QByteArray m_cmapTable; - mutable QFixed m_unitsPerEm; - - // m_openFont and m_openFont are used if Symbian does not provide - // the Font Table API - COpenFont *m_openFont; - mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; -}; - -class QFontEngineS60 : public QFontEngine -{ -public: - QFontEngineS60(const QFontDef &fontDef, const QSymbianTypeFaceExtras *extras); - ~QFontEngineS60(); - - QFixed emSquareSize() const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; - - void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); - - QImage alphaMapForGlyph(glyph_t glyph); - - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - glyph_metrics_t boundingBox_const(glyph_t glyph) const; // Const correctnes quirk. - glyph_metrics_t boundingBox(glyph_t glyph); - - QFixed ascent() const; - QFixed descent() const; - QFixed leading() const; - qreal maxCharWidth() const; - qreal minLeftBearing() const { return 0; } - qreal minRightBearing() const { return 0; } - - QByteArray getSfntTable(uint tag) const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - - static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal); - static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal); - - const char *name() const; - - bool canRender(const QChar *string, int len); - - Type type() const; - - void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const; - void setFontScale(qreal scale); - -private: - friend class QFontPrivate; - friend class QSymbianVGFontGlyphCache; - - QFixed glyphAdvance(HB_Glyph glyph) const; - CFont *fontWithSize(qreal size) const; - static void releaseFont(CFont *&font); - - const QSymbianTypeFaceExtras *m_extras; - CFont* m_originalFont; - const qreal m_originalFontSizeInPixels; - CFont* m_scaledFont; - qreal m_scaledFontSizeInPixels; - CFont* m_activeFont; -}; - -class QFontEngineMultiS60 : public QFontEngineMulti -{ -public: - QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies); - void loadEngine(int at); - - int m_script; - QStringList m_fallbackFamilies; -}; - -QT_END_NAMESPACE - -#endif // QFONTENGINE_S60_P_H diff --git a/src/gui/platforms/s60/qkeymapper_s60.cpp b/src/gui/platforms/s60/qkeymapper_s60.cpp deleted file mode 100644 index 08cfae0d2d..0000000000 --- a/src/gui/platforms/s60/qkeymapper_s60.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qkeymapper_p.h" -#include <private/qcore_symbian_p.h> -#include <e32keys.h> -#include <e32cmn.h> -#include <centralrepository.h> -#include <biditext.h> - -QT_BEGIN_NAMESPACE - -QKeyMapperPrivate::QKeyMapperPrivate() -{ -} - -QKeyMapperPrivate::~QKeyMapperPrivate() -{ -} - -QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent * /* e */) -{ - QList<int> result; - return result; -} - -void QKeyMapperPrivate::clearMappings() -{ - // stub -} - -QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers /* modifiers */) -{ - if (keySym >= Qt::Key_Escape) { - switch (keySym) { - case Qt::Key_Tab: - return QString(QChar('\t')); - case Qt::Key_Return: // fall through - case Qt::Key_Enter: - return QString(QChar('\r')); - default: - return QString(); - } - } - - // Symbian doesn't actually use modifiers, but gives us the character code directly. - - return QString(QChar(keySym)); -} - -#include <e32keys.h> -struct KeyMapping{ - TKeyCode s60KeyCode; - TStdScanCode s60ScanCode; - Qt::Key qtKey; -}; - -using namespace Qt; - -static const KeyMapping keyMapping[] = { - {EKeyBackspace, EStdKeyBackspace, Key_Backspace}, - {EKeyTab, EStdKeyTab, Key_Tab}, - {EKeyEnter, EStdKeyEnter, Key_Enter}, - {EKeyEscape, EStdKeyEscape, Key_Escape}, - {EKeySpace, EStdKeySpace, Key_Space}, - {EKeyDelete, EStdKeyDelete, Key_Delete}, - {EKeyPrintScreen, EStdKeyPrintScreen, Key_SysReq}, - {EKeyPause, EStdKeyPause, Key_Pause}, - {EKeyHome, EStdKeyHome, Key_Home}, - {EKeyEnd, EStdKeyEnd, Key_End}, - {EKeyPageUp, EStdKeyPageUp, Key_PageUp}, - {EKeyPageDown, EStdKeyPageDown, Key_PageDown}, - {EKeyInsert, EStdKeyInsert, Key_Insert}, - {EKeyLeftArrow, EStdKeyLeftArrow, Key_Left}, - {EKeyRightArrow, EStdKeyRightArrow, Key_Right}, - {EKeyUpArrow, EStdKeyUpArrow, Key_Up}, - {EKeyDownArrow, EStdKeyDownArrow, Key_Down}, - {EKeyLeftShift, EStdKeyLeftShift, Key_Shift}, - {EKeyRightShift, EStdKeyRightShift, Key_Shift}, - {EKeyLeftAlt, EStdKeyLeftAlt, Key_Alt}, - {EKeyRightAlt, EStdKeyRightAlt, Key_AltGr}, - {EKeyLeftCtrl, EStdKeyLeftCtrl, Key_Control}, - {EKeyRightCtrl, EStdKeyRightCtrl, Key_Control}, - {EKeyLeftFunc, EStdKeyLeftFunc, Key_Super_L}, - {EKeyRightFunc, EStdKeyRightFunc, Key_Super_R}, - {EKeyCapsLock, EStdKeyCapsLock, Key_CapsLock}, - {EKeyNumLock, EStdKeyNumLock, Key_NumLock}, - {EKeyScrollLock, EStdKeyScrollLock, Key_ScrollLock}, - {EKeyF1, EStdKeyF1, Key_F1}, - {EKeyF2, EStdKeyF2, Key_F2}, - {EKeyF3, EStdKeyF3, Key_F3}, - {EKeyF4, EStdKeyF4, Key_F4}, - {EKeyF5, EStdKeyF5, Key_F5}, - {EKeyF6, EStdKeyF6, Key_F6}, - {EKeyF7, EStdKeyF7, Key_F7}, - {EKeyF8, EStdKeyF8, Key_F8}, - {EKeyF9, EStdKeyF9, Key_F9}, - {EKeyF10, EStdKeyF10, Key_F10}, - {EKeyF11, EStdKeyF11, Key_F11}, - {EKeyF12, EStdKeyF12, Key_F12}, - {EKeyF13, EStdKeyF13, Key_F13}, - {EKeyF14, EStdKeyF14, Key_F14}, - {EKeyF15, EStdKeyF15, Key_F15}, - {EKeyF16, EStdKeyF16, Key_F16}, - {EKeyF17, EStdKeyF17, Key_F17}, - {EKeyF18, EStdKeyF18, Key_F18}, - {EKeyF19, EStdKeyF19, Key_F19}, - {EKeyF20, EStdKeyF20, Key_F20}, - {EKeyF21, EStdKeyF21, Key_F21}, - {EKeyF22, EStdKeyF22, Key_F22}, - {EKeyF23, EStdKeyF23, Key_F23}, - {EKeyF24, EStdKeyF24, Key_F24}, - {EKeyOff, EStdKeyOff, Key_PowerOff}, -// {EKeyMenu, EStdKeyMenu, Key_Menu}, // Menu is EKeyApplication0 - {EKeyHelp, EStdKeyHelp, Key_Help}, - {EKeyDial, EStdKeyDial, Key_Call}, - {EKeyIncVolume, EStdKeyIncVolume, Key_VolumeUp}, - {EKeyDecVolume, EStdKeyDecVolume, Key_VolumeDown}, - {EKeyDevice0, EStdKeyDevice0, Key_Context1}, // Found by manual testing. - {EKeyDevice1, EStdKeyDevice1, Key_Context2}, // Found by manual testing. - {EKeyDevice3, EStdKeyDevice3, Key_Select}, - {EKeyDevice7, EStdKeyDevice7, Key_Camera}, - {EKeyApplication0, EStdKeyApplication0, Key_Menu}, // Found by manual testing. - {EKeyApplication1, EStdKeyApplication1, Key_Launch1}, // Found by manual testing. - {EKeyApplication2, EStdKeyApplication2, Key_MediaPlay}, // Found by manual testing. - {EKeyApplication3, EStdKeyApplication3, Key_MediaStop}, // Found by manual testing. - {EKeyApplication4, EStdKeyApplication4, Key_MediaNext}, // Found by manual testing. - {EKeyApplication5, EStdKeyApplication5, Key_MediaPrevious}, // Found by manual testing. - {EKeyApplication6, EStdKeyApplication6, Key_Launch6}, - {EKeyApplication7, EStdKeyApplication7, Key_Launch7}, - {EKeyApplication8, EStdKeyApplication8, Key_Launch8}, - {EKeyApplication9, EStdKeyApplication9, Key_Launch9}, - {EKeyApplicationA, EStdKeyApplicationA, Key_LaunchA}, - {EKeyApplicationB, EStdKeyApplicationB, Key_LaunchB}, - {EKeyApplicationC, EStdKeyApplicationC, Key_LaunchC}, - {EKeyApplicationD, EStdKeyApplicationD, Key_LaunchD}, - {EKeyApplicationE, EStdKeyApplicationE, Key_LaunchE}, - {EKeyApplicationF, EStdKeyApplicationF, Key_LaunchF}, - {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus}, - {EKeyYes, EStdKeyYes, Key_Yes}, - {EKeyNo, EStdKeyNo, Key_No}, - {TKeyCode(0), TStdScanCode(0), Qt::Key(0)} -}; - -int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key) -{ - int res = Qt::Key_unknown; - for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { - if (keyMapping[i].s60KeyCode == s60key) { - res = keyMapping[i].qtKey; - break; - } - } - return res; -} - -int QKeyMapperPrivate::mapS60ScanCodesToQt(TUint s60scanCode) -{ - int res = Qt::Key_unknown; - for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { - if (keyMapping[i].s60ScanCode == s60scanCode) { - res = keyMapping[i].qtKey; - break; - } - } - return res; -} - -int QKeyMapperPrivate::mapQtToS60Key(int qtKey) -{ - int res = KErrUnknown; - for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { - if (keyMapping[i].qtKey == qtKey) { - res = keyMapping[i].s60KeyCode; - break; - } - } - return res; -} - -int QKeyMapperPrivate::mapQtToS60ScanCodes(int qtKey) -{ - int res = KErrUnknown; - for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { - if (keyMapping[i].qtKey == qtKey) { - res = keyMapping[i].s60ScanCode; - break; - } - } - return res; -} - -void QKeyMapperPrivate::updateInputLanguage() -{ -#ifdef Q_WS_S60 - TInt err; - CRepository *repo; - const TUid KCRUidAknFep = TUid::Uid(0x101F876D); - const TUint32 KAknFepInputTxtLang = 0x00000005; - TRAP(err, repo = CRepository::NewL(KCRUidAknFep)); - if (err != KErrNone) - return; - - TInt symbianLang; - err = repo->Get(KAknFepInputTxtLang, symbianLang); - delete repo; - if (err != KErrNone) - return; - - QString qtLang = QString::fromAscii(qt_symbianLocaleName(symbianLang)); - keyboardInputLocale = QLocale(qtLang); - keyboardInputDirection = (TBidiText::ScriptDirectionality(TLanguage(symbianLang)) == TBidiText::ERightToLeft) - ? Qt::RightToLeft : Qt::LeftToRight; -#else - keyboardInputLocale = QLocale(); - keyboardInputDirection = Qt::LeftToRight; -#endif -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qpaintengine_s60.cpp b/src/gui/platforms/s60/qpaintengine_s60.cpp deleted file mode 100644 index ca303be03d..0000000000 --- a/src/gui/platforms/s60/qpaintengine_s60.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <private/qpaintengine_s60_p.h> -#include <private/qpixmap_s60_p.h> -#include <private/qt_s60_p.h> -#include <private/qvolatileimage_p.h> - -QT_BEGIN_NAMESPACE - -class QS60PaintEnginePrivate : public QRasterPaintEnginePrivate -{ -public: - QS60PaintEnginePrivate() {} -}; - -QS60PaintEngine::QS60PaintEngine(QPaintDevice *device, QS60PixmapData *data) - : QRasterPaintEngine(*(new QS60PaintEnginePrivate), device), pixmapData(data) -{ -} - -bool QS60PaintEngine::begin(QPaintDevice *device) -{ - Q_D(QS60PaintEngine); - - if (pixmapData->classId() == QPixmapData::RasterClass) { - pixmapData->beginDataAccess(); - bool ret = QRasterPaintEngine::begin(device); - // Make sure QPaintEngine::paintDevice() returns the proper device. - // QRasterPaintEngine changes pdev to QImage in case of RasterClass QPixmapData - // which is incorrect in Symbian. - d->pdev = device; - return ret; - } - - return QRasterPaintEngine::begin(device); -} - -bool QS60PaintEngine::end() -{ - if (pixmapData->classId() == QPixmapData::RasterClass) { - bool ret = QRasterPaintEngine::end(); - pixmapData->endDataAccess(); - return ret; - } - return QRasterPaintEngine::end(); -} - -void QS60PaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) -{ - if (pm.pixmapData()->classId() == QPixmapData::RasterClass) { - QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData()); - srcData->beginDataAccess(); - QRasterPaintEngine::drawPixmap(p, pm); - srcData->endDataAccess(); - } else { - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(p, img->imageRef()); - img->endDataAccess(true); - } else { - QRasterPaintEngine::drawPixmap(p, pm); - } - } -} - -void QS60PaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - if (pm.pixmapData()->classId() == QPixmapData::RasterClass) { - QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData()); - srcData->beginDataAccess(); - QRasterPaintEngine::drawPixmap(r, pm, sr); - srcData->endDataAccess(); - } else { - void *nativeData = pm.pixmapData()->toNativeType(QPixmapData::VolatileImage); - if (nativeData) { - QVolatileImage *img = static_cast<QVolatileImage *>(nativeData); - img->beginDataAccess(); - QRasterPaintEngine::drawImage(r, img->imageRef(), sr); - img->endDataAccess(true); - } else { - QRasterPaintEngine::drawPixmap(r, pm, sr); - } - } -} - -void QS60PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr) -{ - if (pm.pixmapData()->classId() == QPixmapData::RasterClass) { - QS60PixmapData *srcData = static_cast<QS60PixmapData *>(pm.pixmapData()); - srcData->beginDataAccess(); - QRasterPaintEngine::drawTiledPixmap(r, pm, sr); - srcData->endDataAccess(); - } else { - QRasterPaintEngine::drawTiledPixmap(r, pm, sr); - } -} - -void QS60PaintEngine::prepare(QImage *image) -{ - QRasterBuffer *buffer = d_func()->rasterBuffer.data(); - if (buffer) - buffer->prepare(image); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qpaintengine_s60_p.h b/src/gui/platforms/s60/qpaintengine_s60_p.h deleted file mode 100644 index a62bdac97c..0000000000 --- a/src/gui/platforms/s60/qpaintengine_s60_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_S60_P_H -#define QPAINTENGINE_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qpaintengine_raster_p.h" - -QT_BEGIN_NAMESPACE - -class QS60PaintEnginePrivate; -class QS60PixmapData; - -class QS60PaintEngine : public QRasterPaintEngine -{ - Q_DECLARE_PRIVATE(QS60PaintEngine) - -public: - QS60PaintEngine(QPaintDevice *device, QS60PixmapData* data); - bool begin(QPaintDevice *device); - bool end(); - - void drawPixmap(const QPointF &p, const QPixmap &pm); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - - void prepare(QImage* image); - -private: - QS60PixmapData *pixmapData; -}; - -QT_END_NAMESPACE - -#endif // QPAINTENGINE_S60_P_H diff --git a/src/gui/platforms/s60/qpixmap_s60.cpp b/src/gui/platforms/s60/qpixmap_s60.cpp deleted file mode 100644 index c8aa003ffa..0000000000 --- a/src/gui/platforms/s60/qpixmap_s60.cpp +++ /dev/null @@ -1,1040 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <exception> -#include <w32std.h> -#include <fbs.h> - -#include <private/qapplication_p.h> -#include <private/qgraphicssystem_p.h> -#include <private/qt_s60_p.h> -#include <private/qpaintengine_s60_p.h> -#include <private/qfont_p.h> - -#include "qpixmap.h" -#include "qpixmap_raster_p.h" -#include <qwidget.h> -#include "qpixmap_s60_p.h" -#include "qnativeimage_p.h" -#include "qbitmap.h" -#include "qimage.h" -#include "qimage_p.h" - -#include <fbs.h> - -QT_BEGIN_NAMESPACE - -const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80 }; - -static bool cleanup_function_registered = false; -static QS60PixmapData *firstPixmap = 0; - -// static -void QS60PixmapData::qt_symbian_register_pixmap(QS60PixmapData *pd) -{ - if (!cleanup_function_registered) { - qAddPostRoutine(qt_symbian_release_pixmaps); - cleanup_function_registered = true; - } - - pd->next = firstPixmap; - pd->prev = 0; - if (firstPixmap) - firstPixmap->prev = pd; - firstPixmap = pd; -} - -// static -void QS60PixmapData::qt_symbian_unregister_pixmap(QS60PixmapData *pd) -{ - if (pd->next) - pd->next->prev = pd->prev; - if (pd->prev) - pd->prev->next = pd->next; - else - firstPixmap = pd->next; -} - -// static -void QS60PixmapData::qt_symbian_release_pixmaps() -{ - // Scan all QS60PixmapData objects in the system and destroy them. - QS60PixmapData *pd = firstPixmap; - while (pd != 0) { - pd->release(); - pd = pd->next; - } -} - -/* - \class QSymbianFbsClient - \since 4.6 - \internal - - Symbian Font And Bitmap server client that is - used to lock the global bitmap heap. Only used in - S60 v3.1 and S60 v3.2. -*/ -_LIT(KFBSERVLargeBitmapAccessName,"FbsLargeBitmapAccess"); -class QSymbianFbsClient -{ -public: - - QSymbianFbsClient() : heapLocked(false) - { - heapLock.OpenGlobal(KFBSERVLargeBitmapAccessName); - } - - ~QSymbianFbsClient() - { - heapLock.Close(); - } - - bool lockHeap() - { - bool wasLocked = heapLocked; - - if (heapLock.Handle() && !heapLocked) { - heapLock.Wait(); - heapLocked = true; - } - - return wasLocked; - } - - bool unlockHeap() - { - bool wasLocked = heapLocked; - - if (heapLock.Handle() && heapLocked) { - heapLock.Signal(); - heapLocked = false; - } - - return wasLocked; - } - - -private: - - RMutex heapLock; - bool heapLocked; -}; - -Q_GLOBAL_STATIC(QSymbianFbsClient, qt_symbianFbsClient); - - - -// QSymbianFbsHeapLock - -QSymbianFbsHeapLock::QSymbianFbsHeapLock(LockAction a) -: action(a), wasLocked(false) -{ - QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); - if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) - wasLocked = qt_symbianFbsClient()->unlockHeap(); -} - -QSymbianFbsHeapLock::~QSymbianFbsHeapLock() -{ - // Do nothing -} - -void QSymbianFbsHeapLock::relock() -{ - QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); - if (wasLocked && (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3)) - qt_symbianFbsClient()->lockHeap(); -} - -/* - \class QSymbianBitmapDataAccess - \since 4.6 - \internal - - Data access class that is used to locks/unlocks pixel data - when drawing or modifying CFbsBitmap pixel data. -*/ -class QSymbianBitmapDataAccess -{ -public: - - static int heapRefCount; - QSysInfo::SymbianVersion symbianVersion; - - explicit QSymbianBitmapDataAccess() - { - symbianVersion = QSysInfo::symbianVersion(); - }; - - ~QSymbianBitmapDataAccess() {}; - - inline void beginDataAccess(CFbsBitmap *bitmap) - { - if (symbianVersion == QSysInfo::SV_9_2) { - if (heapRefCount == 0) - qt_symbianFbsClient()->lockHeap(); - } else { - bitmap->LockHeap(ETrue); - } - - heapRefCount++; - } - - inline void endDataAccess(CFbsBitmap *bitmap) - { - heapRefCount--; - - if (symbianVersion == QSysInfo::SV_9_2) { - if (heapRefCount == 0) - qt_symbianFbsClient()->unlockHeap(); - } else { - bitmap->UnlockHeap(ETrue); - } - } -}; - -int QSymbianBitmapDataAccess::heapRefCount = 0; - - -#define UPDATE_BUFFER() \ - { \ - beginDataAccess(); \ - endDataAccess(); \ -} - - -static CFbsBitmap* createSymbianCFbsBitmap(const TSize& size, TDisplayMode mode) -{ - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - CFbsBitmap* bitmap = 0; - QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap); - - if (bitmap->Create(size, mode) != KErrNone) { - delete bitmap; - bitmap = 0; - } - - lock.relock(); - - return bitmap; -} - -static CFbsBitmap* uncompress(CFbsBitmap* bitmap) -{ - if(bitmap->IsCompressedInRAM()) { - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - CFbsBitmap *uncompressed = 0; - QT_TRAP_THROWING(uncompressed = new (ELeave) CFbsBitmap); - - if (uncompressed->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { - delete bitmap; - bitmap = 0; - lock.relock(); - - return bitmap; - } - - lock.relock(); - - CFbsBitmapDevice* bitmapDevice = 0; - CFbsBitGc *bitmapGc = 0; - QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(uncompressed)); - QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); - bitmapGc->Activate(bitmapDevice); - - bitmapGc->BitBlt(TPoint(), bitmap); - - delete bitmapGc; - delete bitmapDevice; - - return uncompressed; - } else { - return bitmap; - } -} - -QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h) -{ - CWsScreenDevice* screenDevice = S60->screenDevice(); - TSize screenSize = screenDevice->SizeInPixels(); - - TSize srcSize; - // Find out if this is one of our windows. - QSymbianControl *sControl; - sControl = winId->MopGetObject(sControl); - if (sControl && sControl->widget()->windowType() == Qt::Desktop) { - // Grabbing desktop widget - srcSize = screenSize; - } else { - TPoint relativePos = winId->PositionRelativeToScreen(); - x += relativePos.iX; - y += relativePos.iY; - srcSize = winId->Size(); - } - - TRect srcRect(TPoint(x, y), srcSize); - // Clip to the screen - srcRect.Intersection(TRect(screenSize)); - - if (w > 0 && h > 0) { - TRect subRect(TPoint(x, y), TSize(w, h)); - // Clip to the subRect - srcRect.Intersection(subRect); - } - - if (srcRect.IsEmpty()) - return QPixmap(); - - CFbsBitmap* temporary = createSymbianCFbsBitmap(srcRect.Size(), screenDevice->DisplayMode()); - - QPixmap pix; - - if (temporary && screenDevice->CopyScreenToBitmap(temporary, srcRect) == KErrNone) { - pix = QPixmap::fromSymbianCFbsBitmap(temporary); - } - - delete temporary; - return pix; -} - -/*! - \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const - \since 4.6 - - Creates a \c CFbsBitmap that is equivalent to the QPixmap. Internally this - function will try to duplicate the handle instead of copying the data, - however in scenarios where this is not possible the data will be copied. - If the creation fails or the pixmap is null, then this function returns 0. - - It is the caller's responsibility to release the \c CFbsBitmap data - after use either by deleting the bitmap or calling \c Reset(). - - \warning On S60 3.1 and S60 3.2, semi-transparent pixmaps are always copied - and not duplicated. - \warning This function is only available on Symbian OS. - - \sa fromSymbianCFbsBitmap() -*/ -CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const -{ - QPixmapData *data = pixmapData(); - if (!data || data->isNull()) - return 0; - - return reinterpret_cast<CFbsBitmap*>(data->toNativeType(QPixmapData::FbsBitmap)); -} - -/*! - \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) - \since 4.6 - - Creates a QPixmap from a \c CFbsBitmap \a bitmap. Internally this function - will try to duplicate the bitmap handle instead of copying the data, however - in scenarios where this is not possible the data will be copied. - To be sure that QPixmap does not modify your original instance, you should - make a copy of your \c CFbsBitmap before calling this function. - If the CFbsBitmap is not valid this function will return a null QPixmap. - For performance reasons it is recommended to use a \a bitmap with a display - mode of EColor16MAP or EColor16MU whenever possible. - - \warning This function is only available on Symbian OS. - - \sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} -*/ -QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) -{ - if (!bitmap) - return QPixmap(); - - QScopedPointer<QPixmapData> data(QPixmapData::create(0,0, QPixmapData::PixmapType)); - data->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap); - QPixmap pixmap(data.take()); - return pixmap; -} - -QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type), - symbianBitmapDataAccess(new QSymbianBitmapDataAccess), - cfbsBitmap(0), - pengine(0), - bytes(0), - formatLocked(false), - next(0), - prev(0) -{ - qt_symbian_register_pixmap(this); -} - -QS60PixmapData::~QS60PixmapData() -{ - release(); - delete symbianBitmapDataAccess; - qt_symbian_unregister_pixmap(this); -} - -void QS60PixmapData::resize(int width, int height) -{ - if (width <= 0 || height <= 0) { - w = width; - h = height; - is_null = true; - - release(); - return; - } else if (!cfbsBitmap) { - TDisplayMode mode; - if (pixelType() == BitmapType) - mode = EGray2; - else - mode = EColor16MU; - - CFbsBitmap* bitmap = createSymbianCFbsBitmap(TSize(width, height), mode); - fromSymbianBitmap(bitmap); - } else { - - TSize newSize(width, height); - - if(cfbsBitmap->SizeInPixels() != newSize) { - cfbsBitmap->Resize(TSize(width, height)); - if(pengine) { - delete pengine; - pengine = 0; - } - } - - UPDATE_BUFFER(); - } -} - -void QS60PixmapData::release() -{ - if (cfbsBitmap) { - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - delete cfbsBitmap; - lock.relock(); - } - - delete pengine; - image = QImage(); - cfbsBitmap = 0; - pengine = 0; - bytes = 0; -} - -/*! - * Takes ownership of bitmap. Used by window surface - */ -void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat) -{ - Q_ASSERT(bitmap); - - release(); - - cfbsBitmap = bitmap; - formatLocked = lockFormat; - - setSerialNumber(cfbsBitmap->Handle()); - - UPDATE_BUFFER(); - - // Create default palette if needed - if (cfbsBitmap->DisplayMode() == EGray2) { - image.setColorCount(2); - image.setColor(0, QColor(Qt::color0).rgba()); - image.setColor(1, QColor(Qt::color1).rgba()); - - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - image.invertPixels(); - } else if (cfbsBitmap->DisplayMode() == EGray256) { - for (int i=0; i < 256; ++i) - image.setColor(i, qRgb(i, i, i)); - } else if (cfbsBitmap->DisplayMode() == EColor256) { - const TColor256Util *palette = TColor256Util::Default(); - for (int i=0; i < 256; ++i) - image.setColor(i, (QRgb)(palette->Color256(i).Value())); - } -} - -QImage QS60PixmapData::toImage(const QRect &r) const -{ - QS60PixmapData *that = const_cast<QS60PixmapData*>(this); - that->beginDataAccess(); - QImage copy = that->image.copy(r); - that->endDataAccess(); - - return copy; -} - -void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags) -{ - release(); - - QImage sourceImage; - - if (pixelType() == BitmapType) { - sourceImage = img.convertToFormat(QImage::Format_MonoLSB); - } else { - if (img.depth() == 1) { - sourceImage = img.hasAlphaChannel() - ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) - : img.convertToFormat(QImage::Format_RGB32); - } else { - - QImage::Format opaqueFormat = QNativeImage::systemFormat(); - QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied; - - if (!img.hasAlphaChannel() - || ((flags & Qt::NoOpaqueDetection) == 0 - && !const_cast<QImage &>(img).data_ptr()->checkForAlphaPixels())) { - sourceImage = img.convertToFormat(opaqueFormat); - } else { - sourceImage = img.convertToFormat(alphaFormat); - } - } - } - - - QImage::Format destFormat = sourceImage.format(); - TDisplayMode mode; - switch (destFormat) { - case QImage::Format_MonoLSB: - mode = EGray2; - break; - case QImage::Format_RGB32: - mode = EColor16MU; - break; - case QImage::Format_ARGB32_Premultiplied: - if (S60->supportsPremultipliedAlpha) { - mode = Q_SYMBIAN_ECOLOR16MAP; - break; - } else { - destFormat = QImage::Format_ARGB32; - } - // Fall through intended - case QImage::Format_ARGB32: - mode = EColor16MA; - break; - case QImage::Format_Invalid: - return; - default: - qWarning("Image format not supported: %d", image.format()); - return; - } - - cfbsBitmap = createSymbianCFbsBitmap(TSize(sourceImage.width(), sourceImage.height()), mode); - if (!cfbsBitmap) { - qWarning("Could not create CFbsBitmap"); - release(); - return; - } - - setSerialNumber(cfbsBitmap->Handle()); - - const uchar *sptr = const_cast<const QImage &>(sourceImage).bits(); - symbianBitmapDataAccess->beginDataAccess(cfbsBitmap); - uchar *dptr = (uchar*)cfbsBitmap->DataAddress(); - Mem::Copy(dptr, sptr, sourceImage.byteCount()); - symbianBitmapDataAccess->endDataAccess(cfbsBitmap); - - UPDATE_BUFFER(); - - if (destFormat == QImage::Format_MonoLSB) { - image.setColorCount(2); - image.setColor(0, QColor(Qt::color0).rgba()); - image.setColor(1, QColor(Qt::color1).rgba()); - } else { - image.setColorTable(sourceImage.colorTable()); - } -} - -void QS60PixmapData::copy(const QPixmapData *data, const QRect &rect) -{ - const QS60PixmapData *s60Data = static_cast<const QS60PixmapData*>(data); - fromImage(s60Data->toImage(rect), Qt::AutoColor | Qt::OrderedAlphaDither); -} - -bool QS60PixmapData::scroll(int dx, int dy, const QRect &rect) -{ - beginDataAccess(); - bool res = QRasterPixmapData::scroll(dx, dy, rect); - endDataAccess(); - return res; -} - -int QS60PixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const -{ - if (!cfbsBitmap) - return 0; - - switch (metric) { - case QPaintDevice::PdmWidth: - return cfbsBitmap->SizeInPixels().iWidth; - case QPaintDevice::PdmHeight: - return cfbsBitmap->SizeInPixels().iHeight; - case QPaintDevice::PdmWidthMM: - return qRound(cfbsBitmap->SizeInPixels().iWidth * 25.4 / qt_defaultDpiX()); - case QPaintDevice::PdmHeightMM: - return qRound(cfbsBitmap->SizeInPixels().iHeight * 25.4 / qt_defaultDpiY()); - case QPaintDevice::PdmNumColors: - return TDisplayModeUtils::NumDisplayModeColors(cfbsBitmap->DisplayMode()); - case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: - return qt_defaultDpiX(); - case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: - return qt_defaultDpiY(); - case QPaintDevice::PdmDepth: - return TDisplayModeUtils::NumDisplayModeBitsPerPixel(cfbsBitmap->DisplayMode()); - default: - qWarning("QPixmap::metric: Invalid metric command"); - } - return 0; - -} - -void QS60PixmapData::fill(const QColor &color) -{ - if (color.alpha() != 255) { - QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied); - im.fill(PREMUL(color.rgba())); - release(); - fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither); - } else { - beginDataAccess(); - QRasterPixmapData::fill(color); - endDataAccess(); - } -} - -void QS60PixmapData::setMask(const QBitmap &mask) -{ - if (mask.size().isEmpty()) { - if (image.depth() != 1) { - QImage newImage = image.convertToFormat(QImage::Format_RGB32); - release(); - fromImage(newImage, Qt::AutoColor | Qt::OrderedAlphaDither); - } - } else if (image.depth() == 1) { - beginDataAccess(); - QRasterPixmapData::setMask(mask); - endDataAccess(); - } else { - const int w = image.width(); - const int h = image.height(); - - const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB); - QImage newImage = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - for (int y = 0; y < h; ++y) { - const uchar *mscan = imageMask.scanLine(y); - QRgb *tscan = (QRgb *)newImage.scanLine(y); - for (int x = 0; x < w; ++x) { - if (!(mscan[x>>3] & qt_pixmap_bit_mask[x&7])) - tscan[x] = 0; - } - } - release(); - fromImage(newImage, Qt::AutoColor | Qt::OrderedAlphaDither); - } -} - -void QS60PixmapData::setAlphaChannel(const QPixmap &alphaChannel) -{ - QImage img(toImage()); - img.setAlphaChannel(alphaChannel.toImage()); - release(); - fromImage(img, Qt::OrderedDither | Qt::OrderedAlphaDither); -} - -QImage QS60PixmapData::toImage() const -{ - return toImage(QRect()); -} - -QPaintEngine* QS60PixmapData::paintEngine() const -{ - if (!pengine) { - QS60PixmapData *that = const_cast<QS60PixmapData*>(this); - that->pengine = new QS60PaintEngine(&that->image, that); - } - return pengine; -} - -void QS60PixmapData::beginDataAccess() -{ - if(!cfbsBitmap) - return; - - symbianBitmapDataAccess->beginDataAccess(cfbsBitmap); - - uchar* newBytes = (uchar*)cfbsBitmap->DataAddress(); - - TSize size = cfbsBitmap->SizeInPixels(); - - if (newBytes == bytes && image.width() == size.iWidth && image.height() == size.iHeight) - return; - - bytes = newBytes; - TDisplayMode mode = cfbsBitmap->DisplayMode(); - QImage::Format format = qt_TDisplayMode2Format(mode); - // On S60 3.1, premultiplied alpha pixels are stored in a bitmap with 16MA type. - // S60 window surface needs backing store pixmap for transparent window in ARGB32 format. - // In that case formatLocked is true. - if (!formatLocked && format == QImage::Format_ARGB32) - format = QImage::Format_ARGB32_Premultiplied; // pixel data is actually in premultiplied format - - QVector<QRgb> savedColorTable; - if (!image.isNull()) - savedColorTable = image.colorTable(); - - image = QImage(bytes, size.iWidth, size.iHeight, format); - - // Restore the palette or create a default - if (!savedColorTable.isEmpty()) { - image.setColorTable(savedColorTable); - } - - w = size.iWidth; - h = size.iHeight; - d = image.depth(); - is_null = (w <= 0 || h <= 0); - - if (pengine) { - QS60PaintEngine *engine = static_cast<QS60PaintEngine *>(pengine); - engine->prepare(&image); - } -} - -void QS60PixmapData::endDataAccess(bool readOnly) const -{ - Q_UNUSED(readOnly); - - if(!cfbsBitmap) - return; - - symbianBitmapDataAccess->endDataAccess(cfbsBitmap); -} - -/*! - \since 4.6 - - Returns a QPixmap that wraps given \a sgImage graphics resource. - The data should be valid even when original RSgImage handle has been - closed. - - \warning This function is only available on Symbian OS. - - \sa toSymbianRSgImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} -*/ - -QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage) -{ - // It is expected that RSgImage will - // CURRENTLY be used in conjuction with - // OpenVG graphics system - // - // Surely things might change in future - - if (!sgImage) - return QPixmap(); - - QScopedPointer<QPixmapData> data(QPixmapData::create(0,0, QPixmapData::PixmapType)); - data->fromNativeType(reinterpret_cast<void*>(sgImage), QPixmapData::SgImage); - QPixmap pixmap(data.take()); - return pixmap; -} - -/*! -\since 4.6 - -Returns a \c RSgImage that is equivalent to the QPixmap by copying the data. - -It is the caller's responsibility to close/delete the \c RSgImage after use. - -\warning This function is only available on Symbian OS. - -\sa fromSymbianRSgImage() -*/ - -RSgImage *QPixmap::toSymbianRSgImage() const -{ - // It is expected that RSgImage will - // CURRENTLY be used in conjuction with - // OpenVG graphics system - // - // Surely things might change in future - - if (isNull()) - return 0; - - RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmapData()->toNativeType(QPixmapData::SgImage)); - - return sgImage; -} - -void* QS60PixmapData::toNativeType(NativeType type) -{ - if (type == QPixmapData::SgImage) { - return 0; - } else if (type == QPixmapData::FbsBitmap) { - - if (isNull() || !cfbsBitmap) - return 0; - - bool convertToArgb32 = false; - bool needsCopy = false; - - if (!(S60->supportsPremultipliedAlpha)) { - // Convert argb32_premultiplied to argb32 since Symbian 9.2 does - // not support premultipied format. - - if (image.format() == QImage::Format_ARGB32_Premultiplied) { - needsCopy = true; - convertToArgb32 = true; - } - } - - CFbsBitmap *bitmap = 0; - - TDisplayMode displayMode = cfbsBitmap->DisplayMode(); - - if(displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - beginDataAccess(); - image.invertPixels(); - endDataAccess(); - needsCopy = true; - } - - if (needsCopy) { - QImage source; - - if (convertToArgb32) { - beginDataAccess(); - source = image.convertToFormat(QImage::Format_ARGB32); - endDataAccess(); - displayMode = EColor16MA; - } else { - source = image; - } - - CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode); - const uchar *sptr = source.bits(); - symbianBitmapDataAccess->beginDataAccess(newBitmap); - - uchar *dptr = (uchar*)newBitmap->DataAddress(); - Mem::Copy(dptr, sptr, source.byteCount()); - - symbianBitmapDataAccess->endDataAccess(newBitmap); - - bitmap = newBitmap; - } else { - - QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap); - - TInt err = bitmap->Duplicate(cfbsBitmap->Handle()); - if (err != KErrNone) { - qWarning("Could not duplicate CFbsBitmap"); - delete bitmap; - bitmap = 0; - } - } - - if(displayMode == EGray2) { - // restore pixels - beginDataAccess(); - image.invertPixels(); - endDataAccess(); - } - - return reinterpret_cast<void*>(bitmap); - - } - - return 0; -} - -void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) -{ - if (nativeType == QPixmapData::SgImage) { - return; - } else if (nativeType == QPixmapData::FbsBitmap && pixmap) { - - CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); - - bool deleteSourceBitmap = false; - bool needsCopy = false; - -#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE - - // Rasterize extended bitmaps - - TUid extendedBitmapType = bitmap->ExtendedBitmapType(); - if (extendedBitmapType != KNullUid) { - CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA); - - CFbsBitmapDevice *rasterBitmapDev = 0; - QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap)); - - CFbsBitGc *rasterBitmapGc = 0; - TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc); - if (err != KErrNone) { - delete rasterBitmap; - delete rasterBitmapDev; - rasterBitmapDev = 0; - return; - } - - rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap); - - bitmap = rasterBitmap; - - delete rasterBitmapDev; - delete rasterBitmapGc; - - rasterBitmapDev = 0; - rasterBitmapGc = 0; - - deleteSourceBitmap = true; - } -#endif - - - deleteSourceBitmap = bitmap->IsCompressedInRAM(); - CFbsBitmap *sourceBitmap = uncompress(bitmap); - - TDisplayMode displayMode = sourceBitmap->DisplayMode(); - QImage::Format format = qt_TDisplayMode2Format(displayMode); - - QImage::Format opaqueFormat = QNativeImage::systemFormat(); - QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied; - - if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB) - needsCopy = true; - - - type = (format != QImage::Format_MonoLSB) - ? QPixmapData::PixmapType - : QPixmapData::BitmapType; - - if (needsCopy) { - - TSize size = sourceBitmap->SizeInPixels(); - int bytesPerLine = sourceBitmap->ScanLineLength(size.iWidth, displayMode); - - QSymbianBitmapDataAccess da; - da.beginDataAccess(sourceBitmap); - uchar *bytes = (uchar*)sourceBitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); - img = img.copy(); - da.endDataAccess(sourceBitmap); - - if(displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - img.invertPixels(); - } else if(displayMode == EColor16M) { - img = img.rgbSwapped(); // EColor16M is BGR - } - - fromImage(img, Qt::AutoColor); - - if(deleteSourceBitmap) - delete sourceBitmap; - } else { - CFbsBitmap* duplicate = 0; - QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap); - - TInt err = duplicate->Duplicate(sourceBitmap->Handle()); - if (err != KErrNone) { - qWarning("Could not duplicate CFbsBitmap"); - - if(deleteSourceBitmap) - delete sourceBitmap; - - delete duplicate; - return; - } - - fromSymbianBitmap(duplicate); - - if(deleteSourceBitmap) - delete sourceBitmap; - } - } -} - -void QS60PixmapData::convertToDisplayMode(int mode) -{ - const TDisplayMode displayMode = static_cast<TDisplayMode>(mode); - if (!cfbsBitmap || cfbsBitmap->DisplayMode() == displayMode) - return; - if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)) { - qWarning("Cannot convert display mode due to depth mismatch"); - return; - } - - const TSize size = cfbsBitmap->SizeInPixels(); - QScopedPointer<CFbsBitmap> newBitmap(createSymbianCFbsBitmap(size, displayMode)); - - const uchar *sptr = const_cast<const QImage &>(image).bits(); - symbianBitmapDataAccess->beginDataAccess(newBitmap.data()); - uchar *dptr = (uchar*)newBitmap->DataAddress(); - Mem::Copy(dptr, sptr, image.byteCount()); - symbianBitmapDataAccess->endDataAccess(newBitmap.data()); - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - delete cfbsBitmap; - lock.relock(); - cfbsBitmap = newBitmap.take(); - setSerialNumber(cfbsBitmap->Handle()); - UPDATE_BUFFER(); -} - -QPixmapData *QS60PixmapData::createCompatiblePixmapData() const -{ - return new QS60PixmapData(pixelType()); -} - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qpixmap_s60_p.h b/src/gui/platforms/s60/qpixmap_s60_p.h deleted file mode 100644 index c440bbc33a..0000000000 --- a/src/gui/platforms/s60/qpixmap_s60_p.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPIXMAPDATA_S60_P_H -#define QPIXMAPDATA_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/private/qpixmap_raster_p.h> - -QT_BEGIN_NAMESPACE - -class CFbsBitmap; -class CFbsBitmapDevice; -class CFbsBitGc; - -class QSymbianBitmapDataAccess; - -class QSymbianFbsHeapLock -{ -public: - - enum LockAction { - Unlock - }; - - explicit QSymbianFbsHeapLock(LockAction a); - ~QSymbianFbsHeapLock(); - void relock(); - -private: - - LockAction action; - bool wasLocked; -}; - -class QS60PixmapData : public QRasterPixmapData -{ -public: - QS60PixmapData(PixelType type); - ~QS60PixmapData(); - - QPixmapData *createCompatiblePixmapData() const; - - void resize(int width, int height); - void fromImage(const QImage &image, Qt::ImageConversionFlags flags); - void copy(const QPixmapData *data, const QRect &rect); - bool scroll(int dx, int dy, const QRect &rect); - - int metric(QPaintDevice::PaintDeviceMetric metric) const; - void fill(const QColor &color); - void setMask(const QBitmap &mask); - void setAlphaChannel(const QPixmap &alphaChannel); - QImage toImage() const; - QPaintEngine* paintEngine() const; - - void beginDataAccess(); - void endDataAccess(bool readOnly=false) const; - - void* toNativeType(NativeType type); - void fromNativeType(void* pixmap, NativeType type); - - void convertToDisplayMode(int mode); - -private: - void release(); - void fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat=false); - QImage toImage(const QRect &r) const; - - QSymbianBitmapDataAccess *symbianBitmapDataAccess; - - CFbsBitmap *cfbsBitmap; - QPaintEngine *pengine; - uchar* bytes; - - bool formatLocked; - - QS60PixmapData *next; - QS60PixmapData *prev; - - static void qt_symbian_register_pixmap(QS60PixmapData *pd); - static void qt_symbian_unregister_pixmap(QS60PixmapData *pd); - static void qt_symbian_release_pixmaps(); - - friend class QPixmap; - friend class QS60WindowSurface; - friend class QS60PaintEngine; - friend class QS60Data; -}; - -QT_END_NAMESPACE - -#endif // QPIXMAPDATA_S60_P_H - diff --git a/src/gui/platforms/s60/qregion_s60.cpp b/src/gui/platforms/s60/qregion_s60.cpp deleted file mode 100644 index eafff1b965..0000000000 --- a/src/gui/platforms/s60/qregion_s60.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbitmap.h" -#include "qbuffer.h" -#include "qimage.h" -#include "qpolygon.h" -#include "qregion.h" - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qsoftkeymanager_s60.cpp b/src/gui/platforms/s60/qsoftkeymanager_s60.cpp deleted file mode 100644 index 79ed91af5b..0000000000 --- a/src/gui/platforms/s60/qsoftkeymanager_s60.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" -#include "qevent.h" -#include "qbitmap.h" -#include "qstyle.h" -#include "qmenubar.h" -#include "private/qt_s60_p.h" -#include "private/qmenu_p.h" -#include "private/qaction_p.h" -#include "private/qsoftkeymanager_p.h" -#include "private/qsoftkeymanager_s60_p.h" -#include "private/qobject_p.h" -#include <eiksoftkeyimage.h> -#include <eikcmbut.h> - -#ifndef QT_NO_SOFTKEYMANAGER -QT_BEGIN_NAMESPACE - -const int S60_COMMAND_START = 6000; -const int LSK_POSITION = 0; -const int MSK_POSITION = 3; -const int RSK_POSITION = 2; - -QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() : cbaHasImage(4) // 4 since MSK position index is 3 -{ - cachedCbaIconSize[0] = QSize(0,0); - cachedCbaIconSize[1] = QSize(0,0); - cachedCbaIconSize[2] = QSize(0,0); - cachedCbaIconSize[3] = QSize(0,0); -} - -bool QSoftKeyManagerPrivateS60::skipCbaUpdate() -{ - // Lets not update softkeys if - // 1. We don't have application panes, i.e. cba - // 2. Our CBA is not active, i.e. S60 native dialog or menu with custom CBA is shown - // 2.1. Except if thre is no current CBA at all and WindowSoftkeysRespondHint is set - - // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before - // menu/dialog CBA is actually displayed i.e. it is being costructed. - CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer(); - if (!appUiCba) - return true; - // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all - CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current(); - // Check if softkey need to be update even they are not visible - bool cbaRespondsWhenInvisible = false; - QWidget *window = QApplication::activeWindow(); - if (window && (window->windowFlags() & Qt::WindowSoftkeysRespondHint)) - cbaRespondsWhenInvisible = true; - - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) - || (appUiCba != currentCba && !cbaRespondsWhenInvisible)) { - return true; - } - return false; -} - -void QSoftKeyManagerPrivateS60::ensureCbaVisibilityAndResponsiviness(CEikButtonGroupContainer &cba) -{ - RDrawableWindow *cbaWindow = cba.DrawableWindow(); - Q_ASSERT_X(cbaWindow, Q_FUNC_INFO, "Native CBA does not have window!"); - // Make sure CBA is visible, i.e. CBA window is on top - cbaWindow->SetOrdinalPosition(0); - // Qt shares same CBA instance between top-level widgets, - // make sure we are not faded by underlying window. - cbaWindow->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); - // Modal dialogs capture pointer events, but shared cba instance - // shall stay responsive. Raise pointer capture priority to keep - // softkeys responsive in modal dialogs - cbaWindow->SetPointerCapturePriority(1); -} - -void QSoftKeyManagerPrivateS60::clearSoftkeys(CEikButtonGroupContainer &cba) -{ -#ifdef SYMBIAN_VERSION_SYMBIAN3 - QT_TRAP_THROWING( - //EAknSoftkeyEmpty is used, because using -1 adds softkeys without actions on Symbian3 - cba.SetCommandL(0, EAknSoftkeyEmpty, KNullDesC); - cba.SetCommandL(2, EAknSoftkeyEmpty, KNullDesC); - ); -#else - QT_TRAP_THROWING( - //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. - cba.SetCommandL(0, -1, KNullDesC); - // TODO: Should we clear also middle SK? - cba.SetCommandL(2, -1, KNullDesC); - ); -#endif - realSoftKeyActions.clear(); -} - -QString QSoftKeyManagerPrivateS60::softkeyText(QAction &softkeyAction) -{ - // In S60 softkeys and menu items do not support key accelerators (i.e. - // CTRL+X). Therefore, removing the accelerator characters from both softkey - // and menu item texts. - const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); - QString iconText = softkeyAction.iconText(); - return underlineShortCut ? softkeyAction.text() : iconText; -} - -QAction *QSoftKeyManagerPrivateS60::highestPrioritySoftkey(QAction::SoftKeyRole role) -{ - QAction *ret = NULL; - // Priority look up is two level - // 1. First widget with softkeys always has highest priority - for (int level = 0; !ret; level++) { - // 2. Highest priority action within widget - QList<QAction*> actions = requestedSoftKeyActions.values(level); - if (actions.isEmpty()) - break; - qSort(actions.begin(), actions.end(), QSoftKeyManagerPrivateS60::actionPriorityMoreThan); - foreach (QAction *action, actions) { - if (action->softKeyRole() == role) { - ret = action; - break; - } - } - } - return ret; -} - -bool QSoftKeyManagerPrivateS60::actionPriorityMoreThan(const QAction *firstItem, const QAction *secondItem) -{ - return firstItem->priority() > secondItem->priority(); -} - -void QSoftKeyManagerPrivateS60::setNativeSoftkey(CEikButtonGroupContainer &cba, - TInt position, TInt command, const TDesC &text) -{ - // Calling SetCommandL causes CBA redraw - QT_TRAP_THROWING(cba.SetCommandL(position, command, text)); -} - -QPoint QSoftKeyManagerPrivateS60::softkeyIconPosition(int position, QSize sourceSize, QSize targetSize) -{ - QPoint iconPosition(0,0); - switch( AknLayoutUtils::CbaLocation() ) - { - case AknLayoutUtils::EAknCbaLocationBottom: - // RSK must be moved to right, LSK in on correct position by default - if (position == RSK_POSITION) - iconPosition.setX(targetSize.width() - sourceSize.width()); - break; - case AknLayoutUtils::EAknCbaLocationRight: - case AknLayoutUtils::EAknCbaLocationLeft: - // Already in correct position - default: - break; - } - - // Align horizontally to center - iconPosition.setY((targetSize.height() - sourceSize.height()) >> 1); - return iconPosition; -} - -QPixmap QSoftKeyManagerPrivateS60::prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize) -{ - QPixmap target(targetSize); - target.fill(Qt::transparent); - QPainter p; - p.begin(&target); - p.drawPixmap(softkeyIconPosition(position, src.size(), targetSize), src); - p.end(); - return target; -} - -bool QSoftKeyManagerPrivateS60::isOrientationLandscape() -{ - // Hard to believe that there is no public API in S60 to - // get current orientation. This workaround works with currently supported resolutions - return S60->screenHeightInPixels < S60->screenWidthInPixels; -} - -QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int position) -{ - - int index = position; - index += isOrientationLandscape() ? 0 : 1; - if(cachedCbaIconSize[index].isNull()) { - // Only way I figured out to get CBA icon size without RnD SDK, was - // to set some dummy icon to CBA first and then ask CBA button CCoeControl::Size() - // The returned value is cached to avoid unnecessary icon setting every time. - const bool left = (position == LSK_POSITION); - if(position == LSK_POSITION || position == RSK_POSITION) { - CEikImage* tmpImage = NULL; - QT_TRAP_THROWING(tmpImage = new (ELeave) CEikImage); - EikSoftkeyImage::SetImage(cba, *tmpImage, left); // Takes myimage ownership - int command = S60_COMMAND_START + position; - setNativeSoftkey(*cba, position, command, KNullDesC()); - cachedCbaIconSize[index] = qt_TSize2QSize(cba->ControlOrNull(command)->Size()); - EikSoftkeyImage::SetLabel(cba, left); - - if(cachedCbaIconSize[index] == QSize(138,72)) { - // Hack for S60 5.0 (5800) landscape orientation, which return wrong icon size - cachedCbaIconSize[index] = QSize(60,60); - } - } - } - - return cachedCbaIconSize[index]; -} - -bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, - QAction &action, int position) -{ - bool ret = false; - - const bool left = (position == LSK_POSITION); - if(position == LSK_POSITION || position == RSK_POSITION) { - QIcon icon = action.icon(); - if (!icon.isNull()) { - // Get size of CBA icon area based on button position and orientation - QSize requiredIconSize = cbaIconSize(cba, position); - // Get pixmap out of icon based on preferred size, the aspect ratio is kept - QPixmap pmWihtAspectRatio = icon.pixmap(requiredIconSize); - // Native softkeys require that pixmap size is exactly the same as requiredIconSize - // prepareSoftkeyPixmap creates a new pixmap with requiredIconSize and blits the 'pmWihtAspectRatio' - // to correct location of it - QPixmap softkeyPixmap = prepareSoftkeyPixmap(pmWihtAspectRatio, position, requiredIconSize); - - QPixmap softkeyAlpha = softkeyPixmap.alphaChannel(); - // Alpha channel in 5.1 and older devices need to be inverted - // TODO: Switch to use toSymbianCFbsBitmap with invert when available - if(QSysInfo::s60Version() <= QSysInfo::SV_S60_5_1) { - QImage alphaImage = softkeyAlpha.toImage(); - alphaImage.invertPixels(); - softkeyAlpha = QPixmap::fromImage(alphaImage); - } - - CFbsBitmap* nBitmap = softkeyPixmap.toSymbianCFbsBitmap(); - CFbsBitmap* nMask = softkeyAlpha.toSymbianCFbsBitmap(); - - CEikImage* myimage = new (ELeave) CEikImage; - myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transferred - - EikSoftkeyImage::SetImage(cba, *myimage, left); // Takes myimage ownership - cbaHasImage[position] = true; - ret = true; - } else { - // Restore softkey to text based - if (cbaHasImage[position]) { - EikSoftkeyImage::SetLabel(cba, left); - cbaHasImage[position] = false; - } - } - } - return ret; -} - -bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, - QAction::SoftKeyRole role, int position) -{ - QAction *action = highestPrioritySoftkey(role); - if (action) { - setSoftkeyImage(&cba, *action, position); - QString text = softkeyText(*action); - TPtrC nativeText = qt_QString2TPtrC(text); - int command = S60_COMMAND_START + position; -#ifdef SYMBIAN_VERSION_SYMBIAN3 - if (softKeyCommandActions.contains(action)) - command = softKeyCommandActions.value(action); -#endif - setNativeSoftkey(cba, position, command, nativeText); - const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action); - cba.DimCommand(command, dimmed); - realSoftKeyActions.insert(command, action); - return true; - } - return false; -} - -bool QSoftKeyManagerPrivateS60::setLeftSoftkey(CEikButtonGroupContainer &cba) -{ - return setSoftkey(cba, QAction::PositiveSoftKey, LSK_POSITION); -} - -bool QSoftKeyManagerPrivateS60::setMiddleSoftkey(CEikButtonGroupContainer &cba) -{ - // Note: In order to get MSK working, application has to have EAknEnableMSK flag set - // Currently it is not possible very easily) - // For more information see: http://wiki.forum.nokia.com/index.php/Middle_softkey_usage - return setSoftkey(cba, QAction::SelectSoftKey, MSK_POSITION); -} - -bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba) -{ - if (!setSoftkey(cba, QAction::NegativeSoftKey, RSK_POSITION)) { - const Qt::WindowType windowType = initialSoftKeySource - ? initialSoftKeySource->window()->windowType() : Qt::Window; - if (windowType != Qt::Dialog && windowType != Qt::Popup) { - QString text(QSoftKeyManager::tr("Exit")); - TPtrC nativeText = qt_QString2TPtrC(text); - if (cbaHasImage[RSK_POSITION]) { - EikSoftkeyImage::SetLabel(&cba, false); - cbaHasImage[RSK_POSITION] = false; - } - setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText); - cba.DimCommand(EAknSoftkeyExit, false); - return true; - } - } - return false; -} - -void QSoftKeyManagerPrivateS60::setSoftkeys(CEikButtonGroupContainer &cba) -{ - int requestedSoftkeyCount = requestedSoftKeyActions.count(); - const int maxSoftkeyCount = 2; // TODO: differs based on orientation ans S60 versions (some have MSK) - if (requestedSoftkeyCount > maxSoftkeyCount) { - // We have more softkeys than available slots - // Put highest priority negative action to RSK and Options menu with rest of softkey actions to LSK - // TODO: Build menu - setLeftSoftkey(cba); - if(AknLayoutUtils::MSKEnabled()) - setMiddleSoftkey(cba); - setRightSoftkey(cba); - } else { - // We have less softkeys than available slots - // Put softkeys to request slots based on role - setLeftSoftkey(cba); - if(AknLayoutUtils::MSKEnabled()) - setMiddleSoftkey(cba); - setRightSoftkey(cba); - } -} - -void QSoftKeyManagerPrivateS60::updateSoftKeys_sys() -{ - if (skipCbaUpdate()) - return; - - CEikButtonGroupContainer *nativeContainer = S60->buttonGroupContainer(); - Q_ASSERT_X(nativeContainer, Q_FUNC_INFO, "Native CBA does not exist!"); - ensureCbaVisibilityAndResponsiviness(*nativeContainer); - clearSoftkeys(*nativeContainer); - setSoftkeys(*nativeContainer); - - nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation -} - -static void resetMenuBeingConstructed(TAny* /*aAny*/) -{ - S60->menuBeingConstructed = false; -} - -void QSoftKeyManagerPrivateS60::tryDisplayMenuBarL() -{ - CleanupStack::PushL(TCleanupItem(resetMenuBeingConstructed, NULL)); - S60->menuBeingConstructed = true; - S60->menuBar()->TryDisplayMenuBarL(); - CleanupStack::PopAndDestroy(); // Reset menuBeingConstructed to false in all cases -} - -bool QSoftKeyManagerPrivateS60::handleCommand(int command) -{ - QAction *action = realSoftKeyActions.value(command); - if (action) { - bool property = QActionPrivate::get(action)->menuActionSoftkeys; - if (property) { - QT_TRAP_THROWING(tryDisplayMenuBarL()); - } else if (action->menu()) { - // TODO: This is hack, in order to use exising QMenuBar implementation for Symbian - // menubar needs to have widget to which it is associated. Since we want to associate - // menubar to action (which is inherited from QObject), we create and associate QWidget - // to action and pass that for QMenuBar. This associates the menubar to action, and we - // can have own menubar for each action. - QWidget *actionContainer = action->property("_q_action_widget").value<QWidget*>(); - if(!actionContainer) { - actionContainer = new QWidget(action->parentWidget()); - QMenuBar *menuBar = new QMenuBar(actionContainer); - foreach(QAction *menuAction, action->menu()->actions()) { - QMenu *menu = menuAction->menu(); - if(menu) - menuBar->addMenu(menu); - else - menuBar->addAction(menuAction); - } - QVariant v; - v.setValue(actionContainer); - action->setProperty("_q_action_widget", v); - } - qt_symbian_next_menu_from_action(actionContainer); - QT_TRAP_THROWING(tryDisplayMenuBarL()); - } - - Q_ASSERT(action->softKeyRole() != QAction::NoSoftKey); - QWidget *actionParent = action->parentWidget(); - Q_ASSERT_X(actionParent, Q_FUNC_INFO, "No parent set for softkey action!"); - if (actionParent->isEnabled()) { - action->activate(QAction::Trigger); - return true; - } - } - return false; -} - -QT_END_NAMESPACE -#endif //QT_NO_SOFTKEYMANAGER diff --git a/src/gui/platforms/s60/qsoftkeymanager_s60_p.h b/src/gui/platforms/s60/qsoftkeymanager_s60_p.h deleted file mode 100644 index 9cb3787cb8..0000000000 --- a/src/gui/platforms/s60/qsoftkeymanager_s60_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSOFTKEYMANAGER_S60_P_H -#define QSOFTKEYMANAGER_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qbitarray.h" -#include "private/qobject_p.h" -#include "private/qsoftkeymanager_common_p.h" - -QT_BEGIN_HEADER - -#ifndef QT_NO_SOFTKEYMANAGER - -QT_BEGIN_NAMESPACE - -class CEikButtonGroupContainer; -class QAction; - -class QSoftKeyManagerPrivateS60 : public QSoftKeyManagerPrivate -{ - Q_DECLARE_PUBLIC(QSoftKeyManager) - -public: - QSoftKeyManagerPrivateS60(); - -public: - void updateSoftKeys_sys(); - bool handleCommand(int command); - -private: - void tryDisplayMenuBarL(); - bool skipCbaUpdate(); - void ensureCbaVisibilityAndResponsiviness(CEikButtonGroupContainer &cba); - void clearSoftkeys(CEikButtonGroupContainer &cba); - QString softkeyText(QAction &softkeyAction); - QAction *highestPrioritySoftkey(QAction::SoftKeyRole role); - static bool actionPriorityMoreThan(const QAction* item1, const QAction* item2); - void setNativeSoftkey(CEikButtonGroupContainer &cba, TInt position, TInt command, const TDesC& text); - QPoint softkeyIconPosition(int position, QSize sourceSize, QSize targetSize); - QPixmap prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize); - bool isOrientationLandscape(); - QSize cbaIconSize(CEikButtonGroupContainer *cba, int position); - bool setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position); - bool setSoftkey(CEikButtonGroupContainer &cba, QAction::SoftKeyRole role, int position); - bool setLeftSoftkey(CEikButtonGroupContainer &cba); - bool setMiddleSoftkey(CEikButtonGroupContainer &cba); - bool setRightSoftkey(CEikButtonGroupContainer &cba); - void setSoftkeys(CEikButtonGroupContainer &cba); - -private: - QHash<int, QAction*> realSoftKeyActions; - QSize cachedCbaIconSize[4]; - QBitArray cbaHasImage; -}; - - -QT_END_NAMESPACE - -#endif //QT_NO_SOFTKEYMANAGER - -QT_END_HEADER - -#endif // QSOFTKEYMANAGER_S60_P_H diff --git a/src/gui/platforms/s60/qsound_s60.cpp b/src/gui/platforms/s60/qsound_s60.cpp deleted file mode 100644 index acc5c2a56f..0000000000 --- a/src/gui/platforms/s60/qsound_s60.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - - -#ifndef QT_NO_SOUND - -#include "qdir.h" -#include "qapplication.h" -#include "qsound.h" -#include "qsound_p.h" -#include "qfileinfo.h" -#include <private/qcore_symbian_p.h> - -#include <e32std.h> -#include <mdaaudiosampleplayer.h> - -QT_BEGIN_NAMESPACE - -class QAuServerS60; - -class QAuBucketS60 : public QAuBucket, public MMdaAudioPlayerCallback -{ -public: - QAuBucketS60(QAuServerS60 *server, QSound *sound); - ~QAuBucketS60(); - - void play(); - void stop(); - - inline QSound *sound() const { return m_sound; } - -public: // from MMdaAudioPlayerCallback - void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration); - void MapcPlayComplete(TInt aError); - -private: - QSound *m_sound; - QAuServerS60 *m_server; - bool m_prepared; - bool m_playCalled; - CMdaAudioPlayerUtility *m_playUtility; -}; - - -class QAuServerS60 : public QAuServer -{ -public: - QAuServerS60(QObject *parent); - - void init(QSound *s) - { - QAuBucketS60 *bucket = new QAuBucketS60(this, s); - setBucket(s, bucket); - } - - void play(QSound *s) - { - bucket(s)->play(); - } - - void stop(QSound *s) - { - bucket(s)->stop(); - } - - bool okay() { return true; } - - void play(const QString& filename); - -protected: - void playCompleted(QAuBucketS60 *bucket, int error); - -protected: - QAuBucketS60 *bucket(QSound *s) - { - return (QAuBucketS60 *)QAuServer::bucket( s ); - } - - friend class QAuBucketS60; - - // static QSound::play(filename) cannot be stopped, meaning that playCompleted - // will get always called and QSound gets removed form this list. - QList<QSound *> staticPlayingSounds; -}; - -QAuServerS60::QAuServerS60(QObject *parent) : - QAuServer(parent) -{ - setObjectName(QLatin1String("QAuServerS60")); -} - -void QAuServerS60::play(const QString& filename) -{ - QSound *s = new QSound(filename); - staticPlayingSounds.append(s); - play(s); -} - -void QAuServerS60::playCompleted(QAuBucketS60 *bucket, int error) -{ - QSound *sound = bucket->sound(); - if (!error) { - // We need to handle repeats by ourselves, since with Symbian API we don't - // know how many loops have been played when user asks it - if (decLoop(sound)) { - play(sound); - } else { - if (staticPlayingSounds.removeAll(sound)) - delete sound; - } - } else { - // We don't have a way to inform about errors -> just decrement loops - // in order that QSound::isFinished will return true; - while (decLoop(sound) > 0) {} - if (staticPlayingSounds.removeAll(sound)) - delete sound; - } -} - -QAuServer *qt_new_audio_server() -{ - return new QAuServerS60(qApp); -} - -QAuBucketS60::QAuBucketS60(QAuServerS60 *server, QSound *sound) - : m_sound(sound), m_server(server), m_prepared(false), m_playCalled(false) -{ - QString filepath = QFileInfo(m_sound->fileName()).absoluteFilePath(); - filepath = QDir::toNativeSeparators(filepath); - TPtrC filepathPtr(qt_QString2TPtrC(filepath)); - TRAPD(err, m_playUtility = CMdaAudioPlayerUtility::NewL(*this); - m_playUtility->OpenFileL(filepathPtr)); - if (err) { - m_server->playCompleted(this, err); - } -} - -void QAuBucketS60::play() -{ - if (m_prepared) { - // OpenFileL call is completed we can start playing immediately - m_playUtility->Play(); - } else { - m_playCalled = true; - } - -} - -void QAuBucketS60::stop() -{ - m_playCalled = false; - m_playUtility->Stop(); -} - -void QAuBucketS60::MapcPlayComplete(TInt aError) -{ - m_server->playCompleted(this, aError); -} - -void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/) -{ - if (aError) { - m_server->playCompleted(this, aError); - } else { - m_prepared = true; - if (m_playCalled){ - play(); - } - } -} - -QAuBucketS60::~QAuBucketS60() -{ - if (m_playUtility){ - m_playUtility->Stop(); - m_playUtility->Close(); - } - - delete m_playUtility; -} - - -#endif // QT_NO_SOUND - -QT_END_NAMESPACE diff --git a/src/gui/platforms/s60/qt_s60_p.h b/src/gui/platforms/s60/qt_s60_p.h deleted file mode 100644 index 8aba53a168..0000000000 --- a/src/gui/platforms/s60/qt_s60_p.h +++ /dev/null @@ -1,625 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT_S60_P_H -#define QT_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qwindowdefs.h" -#include "private/qcore_symbian_p.h" -#include "qhash.h" -#include "qpoint.h" -#include "QtGui/qfont.h" -#include "QtGui/qimage.h" -#include "QtGui/qevent.h" -#include "qpointer.h" -#include "qapplication.h" -#include "qelapsedtimer.h" -#include "QtCore/qthreadstorage.h" -#include "qwidget_p.h" -#include <w32std.h> -#include <coecntrl.h> -#include <eikenv.h> -#include <eikappui.h> - -#ifdef Q_WS_S60 -#include <AknUtils.h> // AknLayoutUtils -#include <avkon.hrh> // EEikStatusPaneUidTitle -#include <akntitle.h> // CAknTitlePane -#include <akncontext.h> // CAknContextPane -#include <eikspane.h> // CEikStatusPane -#include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader -#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen -#ifdef QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H -#include <akntranseffect.h> // BeginFullScreen -#endif -#endif - -QT_BEGIN_NAMESPACE - -// Application internal HandleResourceChangeL events, -// system events seems to start with 0x10 -const TInt KInternalStatusPaneChange = 0x50000000; - -// For BeginFullScreen(). -const TUint KQtAppExitFlag = 0x400; - -static const int qt_symbian_max_screens = 4; - -//this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 -#define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) - -class Q_AUTOTEST_EXPORT QS60ThreadLocalData -{ -public: - QS60ThreadLocalData(); - ~QS60ThreadLocalData(); - bool usingCONEinstances; - RWsSession wsSession; - CWsScreenDevice *screenDevice; -}; - -class QS60Data -{ -public: - QS60Data(); - QThreadStorage<QS60ThreadLocalData *> tls; - TUid uid; - int screenDepth; - QPoint lastCursorPos; - QPoint lastPointerEventPos; - QPointer<QWidget> lastPointerEventTarget; - QPointer<QWidget> mousePressTarget; - int screenWidthInPixels; - int screenHeightInPixels; - int screenWidthInTwips; - int screenHeightInTwips; - int defaultDpiX; - int defaultDpiY; - WId curWin; - enum PressedKeys { - Select = 0x1, - Right = 0x2, - Down = 0x4, - Left = 0x8, - Up = 0x10, - LeftUp = 0x20, - RightUp = 0x40, - RightDown = 0x80, - LeftDown = 0x100 - }; - int virtualMousePressedKeys; // of the above type, but avoids casting problems - int virtualMouseAccelDX; - int virtualMouseAccelDY; - QElapsedTimer virtualMouseAccelTimeout; - int virtualMouseMaxAccel; -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - int brokenPointerCursors : 1; -#endif - int hasTouchscreen : 1; - int mouseInteractionEnabled : 1; - int virtualMouseRequired : 1; - int qtOwnsS60Environment : 1; - int supportsPremultipliedAlpha : 1; - int avkonComponentsSupportTransparency : 1; - int menuBeingConstructed : 1; - int orientationSet : 1; - int partial_keyboard : 1; - QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type - QPointer<QWidget> splitViewLastWidget; - - static CEikButtonGroupContainer *cba; - - enum ScanCodeState { - Unpressed, - KeyDown, - KeyDownAndKey - }; - QHash<TInt, ScanCodeState> scanCodeStates; - - static inline void updateScreenSize(); - inline RWsSession& wsSession(); - static inline int screenCount(); - static inline RWindowGroup& windowGroup(); - static inline RWindowGroup& windowGroup(const QWidget *widget); - static inline RWindowGroup& windowGroup(int screenNumber); - inline CWsScreenDevice* screenDevice(); - inline CWsScreenDevice* screenDevice(const QWidget *widget); - inline CWsScreenDevice* screenDevice(int screenNumber); - static inline int screenNumberForWidget(const QWidget *widget); - static inline CCoeAppUi* appUi(); - static inline CEikMenuBar* menuBar(); -#ifdef Q_WS_S60 - static inline CEikStatusPane* statusPane(); - static inline CCoeControl* statusPaneSubPane(TInt aPaneId); - static inline CAknTitlePane* titlePane(); - static inline CAknContextPane* contextPane(); - static inline CEikButtonGroupContainer* buttonGroupContainer(); - static inline void setButtonGroupContainer(CEikButtonGroupContainer* newCba); - static void setStatusPaneAndButtonGroupVisibility(bool statusPaneVisible, bool buttonGroupVisible); - static bool setRecursiveDecorationsVisibility(QWidget *window, Qt::WindowStates newState); -#endif - static void controlVisibilityChanged(CCoeControl *control, bool visible); - -#ifdef Q_OS_SYMBIAN - TTrapHandler *s60InstalledTrapHandler; -#endif - - int screenWidthInPixelsForScreen[qt_symbian_max_screens]; - int screenHeightInPixelsForScreen[qt_symbian_max_screens]; - int screenWidthInTwipsForScreen[qt_symbian_max_screens]; - int screenHeightInTwipsForScreen[qt_symbian_max_screens]; - - int nativeScreenWidthInPixels; - int nativeScreenHeightInPixels; - - int beginFullScreenCalled : 1; - int endFullScreenCalled : 1; -}; - -Q_AUTOTEST_EXPORT QS60Data* qGlobalS60Data(); -#define S60 qGlobalS60Data() - -class QAbstractLongTapObserver -{ -public: - virtual void HandleLongTapEventL( const TPoint& aPenEventLocation, - const TPoint& aPenEventScreenLocation ) = 0; -}; -class QLongTapTimer; - - -class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver -#ifdef Q_WS_S60 -, public MAknFadedComponent, public MEikStatusPaneObserver -#endif -{ -public: - DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII. - -public: - QSymbianControl(QWidget *w); - void ConstructL(bool isWindowOwning = false, bool desktop = false); - ~QSymbianControl(); - void HandleResourceChange(int resourceType); - void HandlePointerEventL(const TPointerEvent& aPointerEvent); - TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType); -#if !defined(QT_NO_IM) && defined(Q_WS_S60) - TCoeInputCapabilities InputCapabilities() const; -#endif - TTypeUid::Ptr MopSupplyObject(TTypeUid id); - - inline QWidget* widget() const { return qwidget; } - void setWidget(QWidget *w); - void sendInputEvent(QWidget *widget, QInputEvent *inputEvent); - void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; } - void CancelLongTapTimer(); - - void setFocusSafely(bool focus); - - bool isControlActive(); - - void ensureFixNativeOrientation(); - QPoint translatePointForFixedNativeOrientation(const TPoint &pointerEventPos) const; - TRect translateRectForFixedNativeOrientation(const TRect &controlRect) const; - -#ifdef Q_WS_S60 - void FadeBehindPopup(bool fade){ popupFader.FadeBehindPopup( this, this, fade); } - void HandleStatusPaneSizeChange(); - -protected: // from MAknFadedComponent - TInt CountFadedComponents() {return 1;} - CCoeControl* FadedComponent(TInt /*aIndex*/) {return this;} -#else - // #warning No fallback implementation for QSymbianControl::FadeBehindPopup - void FadeBehindPopup(bool /*fade*/){ } -#endif - -protected: - void Draw(const TRect& aRect) const; - void SizeChanged(); - void PositionChanged(); - void FocusChanged(TDrawNow aDrawNow); - -protected: - void qwidgetResize_helper(const QSize &newSize); - -private: - void HandlePointerEvent(const TPointerEvent& aPointerEvent); - TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType); - TKeyResponse sendSymbianKeyEvent(const TKeyEvent &keyEvent, QEvent::Type type); - TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); - TKeyResponse handleVirtualMouse(const TKeyEvent& keyEvent,TEventCode type); - bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); - void sendMouseEvent( - QWidget *receiver, - QEvent::Type type, - const QPoint &globalPos, - Qt::MouseButton button, - Qt::KeyboardModifiers modifiers); - void processTouchEvent(int pointerNumber, TPointerEvent::TType type, QPointF screenPos, qreal pressure); - void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ); -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); -#endif - bool isSplitViewWidget(QWidget *widget); - -public: - void handleClientAreaChange(); - -private: - static QSymbianControl *lastFocusedControl; - -private: - QWidget *qwidget; - QLongTapTimer* m_longTapDetector; - QElapsedTimer m_doubleClickTimer; - bool m_ignoreFocusChanged : 1; - bool m_symbianPopupIsOpen : 1; - -#ifdef Q_WS_S60 - // Fader object used to fade everything except this menu and the CBA. - TAknPopupFader popupFader; -#endif - - bool m_inExternalScreenOverride : 1; - bool m_lastStatusPaneVisibility : 1; -}; - -inline QS60Data::QS60Data() -: uid(TUid::Null()), - screenDepth(0), - screenWidthInPixels(0), - screenHeightInPixels(0), - screenWidthInTwips(0), - screenHeightInTwips(0), - defaultDpiX(0), - defaultDpiY(0), - curWin(0), - virtualMousePressedKeys(0), - virtualMouseAccelDX(0), - virtualMouseAccelDY(0), - virtualMouseMaxAccel(0), -#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - brokenPointerCursors(0), -#endif - hasTouchscreen(0), - mouseInteractionEnabled(0), - virtualMouseRequired(0), - qtOwnsS60Environment(0), - supportsPremultipliedAlpha(0), - avkonComponentsSupportTransparency(0), - menuBeingConstructed(0), - orientationSet(0), - partial_keyboard(0), - s60ApplicationFactory(0) -#ifdef Q_OS_SYMBIAN - ,s60InstalledTrapHandler(0) -#endif - ,beginFullScreenCalled(0), - endFullScreenCalled(0) -{ -} - -inline void QS60Data::updateScreenSize() -{ - CWsScreenDevice *dev = S60->screenDevice(); - int screenModeCount = dev->NumScreenModes(); - int mode = dev->CurrentScreenMode(); - TPixelsTwipsAndRotation params; - dev->GetScreenModeSizeAndRotation(mode, params); - S60->screenWidthInPixels = params.iPixelSize.iWidth; - S60->screenHeightInPixels = params.iPixelSize.iHeight; - S60->screenWidthInTwips = params.iTwipsSize.iWidth; - S60->screenHeightInTwips = params.iTwipsSize.iHeight; - - S60->virtualMouseMaxAccel = qMax(S60->screenHeightInPixels, S60->screenWidthInPixels) / 10; - - TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch; - S60->defaultDpiY = S60->screenHeightInPixels / inches; - inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch; - S60->defaultDpiX = S60->screenWidthInPixels / inches; - - int screens = S60->screenCount(); - for (int i = 0; i < screens; ++i) { - CWsScreenDevice *dev = S60->screenDevice(i); - mode = dev->CurrentScreenMode(); - dev->GetScreenModeSizeAndRotation(mode, params); - S60->screenWidthInPixelsForScreen[i] = params.iPixelSize.iWidth; - S60->screenHeightInPixelsForScreen[i] = params.iPixelSize.iHeight; - S60->screenWidthInTwipsForScreen[i] = params.iTwipsSize.iWidth; - S60->screenHeightInTwipsForScreen[i] = params.iTwipsSize.iHeight; - } - - // Look for a screen mode with rotation 0 - // in order to decide what the native orientation is. - for (mode = 0; mode < screenModeCount; ++mode) { - TPixelsAndRotation sizeAndRotation; - dev->GetScreenModeSizeAndRotation(mode, sizeAndRotation); - if (sizeAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationNormal) { - S60->nativeScreenWidthInPixels = sizeAndRotation.iPixelSize.iWidth; - S60->nativeScreenHeightInPixels = sizeAndRotation.iPixelSize.iHeight; - break; - } - } -} - -inline RWsSession& QS60Data::wsSession() -{ - if(!tls.hasLocalData()) { - tls.setLocalData(new QS60ThreadLocalData); - } - return tls.localData()->wsSession; -} - -inline int QS60Data::screenCount() -{ -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - CCoeEnv *env = CCoeEnv::Static(); - if (env) { - return qMin(env->WsSession().NumberOfScreens(), qt_symbian_max_screens); - } -#endif - return 1; -} - -inline RWindowGroup& QS60Data::windowGroup() -{ - return CCoeEnv::Static()->RootWin(); -} - -inline RWindowGroup& QS60Data::windowGroup(const QWidget *widget) -{ - return windowGroup(screenNumberForWidget(widget)); -} - -inline RWindowGroup& QS60Data::windowGroup(int screenNumber) -{ -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - RWindowGroup *wg = CCoeEnv::Static()->RootWin(screenNumber); - return wg ? *wg : windowGroup(); -#else - Q_UNUSED(screenNumber); - return windowGroup(); -#endif -} - -inline CWsScreenDevice* QS60Data::screenDevice() -{ - if(!tls.hasLocalData()) { - tls.setLocalData(new QS60ThreadLocalData); - } - return tls.localData()->screenDevice; -} - -inline CWsScreenDevice* QS60Data::screenDevice(const QWidget *widget) -{ - return screenDevice(screenNumberForWidget(widget)); -} - -inline CWsScreenDevice* QS60Data::screenDevice(int screenNumber) -{ -#if defined(Q_SYMBIAN_SUPPORTS_MULTIPLE_SCREENS) - CCoeEnv *env = CCoeEnv::Static(); - if (env) { - CWsScreenDevice *dev = env->ScreenDevice(screenNumber); - return dev ? dev : screenDevice(); - } else { - return screenDevice(); - } -#else - return screenDevice(); -#endif -} - -inline int QS60Data::screenNumberForWidget(const QWidget *widget) -{ - if (!widget) - return 0; - const QWidget *w = widget; - while (w->parentWidget()) - w = w->parentWidget(); - return qt_widget_private(const_cast<QWidget *>(w))->symbianScreenNumber; -} - -inline CCoeAppUi* QS60Data::appUi() -{ - return CCoeEnv::Static()-> AppUi(); -} - -inline CEikMenuBar* QS60Data::menuBar() -{ - return CEikonEnv::Static()->AppUiFactory()->MenuBar(); -} - -#ifdef Q_WS_S60 -inline CEikStatusPane* QS60Data::statusPane() -{ - return CEikonEnv::Static()->AppUiFactory()->StatusPane(); -} - -// Returns the application's status pane control, if not present returns NULL. -inline CCoeControl* QS60Data::statusPaneSubPane( TInt aPaneId ) -{ - const TUid paneUid = { aPaneId }; - CEikStatusPane* statusPane = S60->statusPane(); - if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) { - CCoeControl* control = NULL; - // ControlL shouldn't leave because the pane is present - TRAPD(err, control = statusPane->ControlL(paneUid)); - return err != KErrNone ? NULL : control; - } - return NULL; -} - -// Returns the application's title pane, if not present returns NULL. -inline CAknTitlePane* QS60Data::titlePane() -{ - return static_cast<CAknTitlePane*>(S60->statusPaneSubPane(EEikStatusPaneUidTitle)); -} - -// Returns the application's title pane, if not present returns NULL. -inline CAknContextPane* QS60Data::contextPane() -{ - return static_cast<CAknContextPane*>(S60->statusPaneSubPane(EEikStatusPaneUidContext)); -} - -inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer() -{ - return QS60Data::cba; -} - -inline void QS60Data::setButtonGroupContainer(CEikButtonGroupContainer *newCba) -{ - QS60Data::cba = newCba; -} -#endif // Q_WS_S60 - -static inline QFont qt_TFontSpec2QFontL(const TFontSpec &fontSpec) -{ - return QFont( - qt_TDesC2QString(fontSpec.iTypeface.iName), - fontSpec.iHeight / KTwipsPerPoint, - fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightNormal ? QFont::Normal : QFont::Bold, - fontSpec.iFontStyle.Posture() == EPostureItalic - ); -} - -static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode) -{ - QImage::Format format; - switch(mode) { - case EGray2: - format = QImage::Format_MonoLSB; - break; - case EColor256: - case EGray256: - format = QImage::Format_Indexed8; - break; - case EColor4K: - format = QImage::Format_RGB444; - break; - case EColor64K: - format = QImage::Format_RGB16; - break; - case EColor16M: - format = QImage::Format_RGB888; - break; - case EColor16MU: - format = QImage::Format_RGB32; - break; - case EColor16MA: - format = QImage::Format_ARGB32; - break; - case Q_SYMBIAN_ECOLOR16MAP: - format = QImage::Format_ARGB32_Premultiplied; - break; - default: - format = QImage::Format_Invalid; - break; - } - return format; -} - -#ifndef QT_NO_CURSOR -void qt_symbian_setWindowCursor(const QCursor &cursor, const CCoeControl* wid); -void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &node); -void qt_symbian_setGlobalCursor(const QCursor &cursor); -void qt_symbian_set_cursor_visible(bool visible); -bool qt_symbian_is_cursor_visible(); -#endif - -static inline bool qt_beginFullScreenEffect() -{ -#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) - // Only for post-S^3. On earlier versions the system transition effects - // may not be able to capture the non-Avkon content, leading to confusing - // looking effects, so just skip the whole thing. - if (S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) - return false; - S60->beginFullScreenCalled = true; - // For Avkon apps the app-exit effect is triggered from CAknAppUi::PrepareToExit(). - // That is good for Avkon apps, but in case of Qt the RWindows are destroyed earlier. - // Therefore we call BeginFullScreen() ourselves. - GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit, - TRect(0, 0, 0, 0), - AknTransEffect::EParameterType, - AknTransEffect::GfxTransParam(S60->uid, - AknTransEffect::TParameter::EAvkonCheck | KQtAppExitFlag)); - return true; -#else - return false; -#endif -} - -static inline void qt_abortFullScreenEffect() -{ -#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) - if (!S60->beginFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) - return; - GfxTransEffect::AbortFullScreen(); - S60->beginFullScreenCalled = S60->endFullScreenCalled = false; -#endif -} - -static inline void qt_endFullScreenEffect() -{ -#if defined(Q_WS_S60) && defined(QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H) - if (S60->endFullScreenCalled || QSysInfo::s60Version() <= QSysInfo::SV_S60_5_2) - return; - S60->endFullScreenCalled = true; - GfxTransEffect::EndFullScreen(); -#endif -} - -QT_END_NAMESPACE - -#endif // QT_S60_P_H diff --git a/src/gui/platforms/s60/qwidget_s60.cpp b/src/gui/platforms/s60/qwidget_s60.cpp deleted file mode 100644 index e28a75a6ab..0000000000 --- a/src/gui/platforms/s60/qwidget_s60.cpp +++ /dev/null @@ -1,1450 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwidget_p.h" -#include "qdesktopwidget.h" -#include "qapplication.h" -#include "qapplication_p.h" -#include "private/qbackingstore_p.h" -#include "qevent.h" -#include "qt_s60_p.h" - -#include "qbitmap.h" -#include "private/qwindowsurface_s60_p.h" - -#include <qinputcontext.h> - -#ifdef Q_WS_S60 -#include <aknappui.h> -#include <eikbtgpc.h> -#endif - -// This is necessary in order to be able to perform delayed invocation on slots -// which take arguments of type WId. One example is -// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of -// CCoeControl objects until after the CONE event handler has finished running. -Q_DECLARE_METATYPE(WId) - -// Workaround for the fact that S60 SDKs 3.x do not contain the akntoolbar.h -// header, even though the documentation says that it should be there, and indeed -// it is present in the library. -class CAknToolbar : public CAknControl, - public MCoeControlObserver, - public MCoeControlBackground, - public MEikCommandObserver, - public MAknFadedComponent -{ -public: - IMPORT_C void SetToolbarVisibility(const TBool visible); -}; - -QT_BEGIN_NAMESPACE - -extern bool qt_nograb(); - -QWidget *QWidgetPrivate::mouseGrabber = 0; -QWidget *QWidgetPrivate::keyboardGrabber = 0; -CEikButtonGroupContainer *QS60Data::cba = 0; - -int qt_symbian_create_desktop_on_screen = -1; - -static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) -{ - if ( a.count() != b.count()) - return false; - int index=0; - while (index<a.count()) { - if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole()) - return false; - if (a.at(index)->text().compare(b.at(index)->text())!=0) - return false; - index++; - } - return true; -} - -void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) -{ - // Note: based on x11 implementation - - static const int XCOORD_MAX = 16383; - static const int WRECT_MAX = 16383; - - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - /* - There are up to four different coordinate systems here: - Qt coordinate system for this widget. - Symbian coordinate system for this widget (relative to wrect). - Qt coordinate system for parent - Symbian coordinate system for parent (relative to parent's wrect). - */ - - QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); - QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); - QRect wrect; - //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) - QRect xrect = data.crect; - - const QWidget *const parent = q->parentWidget(); - QRect parentWRect = parent->data->wrect; - - if (parentWRect.isValid()) { - // parent is clipped, and we have to clip to the same limit as parent - if (!parentWRect.contains(xrect)) { - xrect &= parentWRect; - wrect = xrect; - //translate from parent's to my Qt coord sys - wrect.translate(-data.crect.topLeft()); - } - //translate from parent's Qt coords to parent's X coords - xrect.translate(-parentWRect.topLeft()); - - } else { - // parent is not clipped, we may or may not have to clip - - if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) { - // This is where the main optimization is: we are already - // clipped, and if our clip is still valid, we can just - // move our window, and do not need to move or clip - // children - - QRect vrect = xrect & parent->rect(); - vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords - if (data.wrect.contains(vrect)) { - xrect = data.wrect; - xrect.translate(data.crect.topLeft()); - if (data.winid) - data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height())); - return; - } - } - - if (!validRange.contains(xrect)) { - // we are too big, and must clip - xrect &=wrectRange; - wrect = xrect; - wrect.translate(-data.crect.topLeft()); - //parent's X coord system is equal to parent's Qt coord - //sys, so we don't need to map xrect. - } - } - - // unmap if we are outside the valid window system coord system - bool outsideRange = !xrect.isValid(); - bool mapWindow = false; - if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) { - q->setAttribute(Qt::WA_OutsideWSRange, outsideRange); - if (outsideRange) { - if (data.winid) - data.winid->DrawableWindow()->SetVisible(EFalse); - q->setAttribute(Qt::WA_Mapped, false); - } else if (!q->isHidden()) { - mapWindow = true; - } - } - - if (outsideRange) - return; - - bool jump = (data.wrect != wrect); - data.wrect = wrect; - - // and now recursively for all children... - for (int i = 0; i < children.size(); ++i) { - QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(object); - if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) - w->d_func()->setWSGeometry(jump); - } - } - - if (data.winid) { - // move ourselves to the new position and map (if necessary) after - // the movement. Rationale: moving unmapped windows is much faster - // than moving mapped windows - if (!parent->internalWinId()) - xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0))); - - data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height())); - } - - if (mapWindow and !dontShow) { - q->setAttribute(Qt::WA_Mapped); - if (q->internalWinId()) - q->internalWinId()->DrawableWindow()->SetVisible(ETrue); - } - - if (jump && data.winid) { - RWindow *const window = static_cast<RWindow *>(data.winid->DrawableWindow()); - window->Invalidate(TRect(0, 0, wrect.width(), wrect.height())); - } -} - -void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) -{ - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if ((q->windowType() == Qt::Desktop)) - return; - - QPoint oldPos(q->pos()); - QSize oldSize(q->size()); - QRect oldGeom(data.crect); - - // Lose maximized status if deliberate resize - if (w != oldSize.width() || h != oldSize.height()) - data.window_state &= ~Qt::WindowMaximized; - - if (extra) { // any size restrictions? - w = qMin(w,extra->maxw); - h = qMin(h,extra->maxh); - w = qMax(w,extra->minw); - h = qMax(h,extra->minh); - } - - if (q->isWindow()) - topData()->normalGeometry = QRect(0, 0, -1, -1); - else { - uint s = data.window_state; - s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen); - data.window_state = s; - } - - bool isResize = w != oldSize.width() || h != oldSize.height(); - if (!isMove && !isResize) - return; - - if (q->isWindow()) { - if (w == 0 || h == 0) { - q->setAttribute(Qt::WA_OutsideWSRange, true); - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) - hide_sys(); - data.crect = QRect(x, y, w, h); - data.window_state &= ~Qt::WindowFullScreen; - } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { - q->setAttribute(Qt::WA_OutsideWSRange, false); - - // put the window in its place and show it - q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h))); - data.crect.setRect(x, y, w, h); - show_sys(); - } else { - QRect r = QRect(x, y, w, h); - data.crect = r; - q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h))); - topData()->normalGeometry = data.crect; - } - QSymbianControl *window = static_cast<QSymbianControl *>(q->internalWinId()); - window->ensureFixNativeOrientation(); - } else { - data.crect.setRect(x, y, w, h); - - QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; - - if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) { - // Top-level resize optimization does not work for native child widgets; - // disable it for this particular widget. - if (inTopLevelResize) - tlwExtra->inTopLevelResize = false; - if (!isResize && maybeBackingStore()) - moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y()); - else - invalidateBuffer_resizeHelper(oldPos, oldSize); - - if (inTopLevelResize) - tlwExtra->inTopLevelResize = true; - } - if (q->testAttribute(Qt::WA_WState_Created)) - setWSGeometry(); - } - - if (q->isVisible()) { - if (isMove && q->pos() != oldPos) { - QMoveEvent e(q->pos(), oldPos); - QApplication::sendEvent(q, &e); - } - if (isResize) { - bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra - && !extra->topextra->inTopLevelResize; - if (setTopLevelResize) - extra->topextra->inTopLevelResize = true; - QResizeEvent e(q->size(), oldSize); - QApplication::sendEvent(q, &e); - if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId()) - q->internalWinId()->DrawDeferred(); - if (setTopLevelResize) - extra->topextra->inTopLevelResize = false; - } - } else { - if (isMove && q->pos() != oldPos) - q->setAttribute(Qt::WA_PendingMoveEvent, true); - if (isResize) - q->setAttribute(Qt::WA_PendingResizeEvent, true); - } -} - -void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow) -{ - Q_Q(QWidget); - - Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - bool desktop = (type == Qt::Desktop); - //bool tool = (type == Qt::Tool || type == Qt::Drawer); - - if (popup) - flags |= Qt::WindowStaysOnTopHint; // a popup stays on top - - TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); - int sw = clientRect.Width(); - int sh = clientRect.Height(); - - if (desktop) { - symbianScreenNumber = qMax(qt_symbian_create_desktop_on_screen, 0); - TSize screenSize = S60->screenDevice(symbianScreenNumber)->SizeInPixels(); - data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight); - q->setAttribute(Qt::WA_DontShowOnScreen); - } else if (topLevel && !q->testAttribute(Qt::WA_Resized)){ - int width = sw; - int height = sh; - if (symbianScreenNumber > 0) { - TSize screenSize = S60->screenDevice(symbianScreenNumber)->SizeInPixels(); - width = screenSize.iWidth; - height = screenSize.iHeight; - } - if (extra) { - width = qMax(qMin(width, extra->maxw), extra->minw); - height = qMax(qMin(height, extra->maxh), extra->minh); - } - data.crect.setSize(QSize(width, height)); - } - - CCoeControl *const destroyw = destroyOldWindow ? data.winid : 0; - - createExtra(); - if (window) { - setWinId(window); - TRect tr = window->Rect(); - data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height()); - - } else if (topLevel) { - if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen)) - data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY)); - - QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); - Q_CHECK_PTR(control); - - QT_TRAP_THROWING(control->ConstructL(true, desktop)); - control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); - - // Symbian windows are always created in an inactive state - // We perform this assignment for the case where the window is being re-created - // as a result of a call to setParent_sys, on either this widget or one of its - // ancestors. - extra->activated = 0; - - if (!desktop) { - TInt stackingFlags; - if ((q->windowType() & Qt::Popup) == Qt::Popup) { - stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus; - } else { - stackingFlags = ECoeStackFlagStandard; - } - control->MakeVisible(false); - QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); - // Avoid keyboard focus to a hidden window. - control->setFocusSafely(false); - - RDrawableWindow *const drawableWindow = control->DrawableWindow(); - // Request mouse move events. - drawableWindow->PointerFilter(EPointerFilterEnterExit - | EPointerFilterMove | EPointerFilterDrag, 0); - drawableWindow->EnableVisibilityChangeEvents(); - - } - - q->setAttribute(Qt::WA_WState_Created); - - int x, y, w, h; - data.crect.getRect(&x, &y, &w, &h); - control->SetRect(TRect(TPoint(x, y), TSize(w, h))); - - // We wait until the control is fully constructed before calling setWinId, because - // this generates a WinIdChanged event. - setWinId(control.take()); - - if (!desktop) - s60UpdateIsOpaque(); // must be called after setWinId() - - } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget - - QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); - Q_CHECK_PTR(control); - - QT_TRAP_THROWING(control->ConstructL(!parentWidget)); - - // Symbian windows are always created in an inactive state - // We perform this assignment for the case where the window is being re-created - // as a result of a call to setParent_sys, on either this widget or one of its - // ancestors. - extra->activated = 0; - - TInt stackingFlags; - if ((q->windowType() & Qt::Popup) == Qt::Popup) { - stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus; - } else { - stackingFlags = ECoeStackFlagStandard; - } - control->MakeVisible(false); - QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); - // Avoid keyboard focus to a hidden window. - control->setFocusSafely(false); - - q->setAttribute(Qt::WA_WState_Created); - int x, y, w, h; - data.crect.getRect(&x, &y, &w, &h); - control->SetRect(TRect(TPoint(x, y), TSize(w, h))); - - RDrawableWindow *const drawableWindow = control->DrawableWindow(); - // Request mouse move events. - drawableWindow->PointerFilter(EPointerFilterEnterExit - | EPointerFilterMove | EPointerFilterDrag, 0); - drawableWindow->EnableVisibilityChangeEvents(); - - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) { - activateSymbianWindow(control.data()); - control->MakeVisible(true); - } - - // We wait until the control is fully constructed before calling setWinId, because - // this generates a WinIdChanged event. - setWinId(control.take()); - } - - if (destroyw) { - destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw); - - // Delay deletion of the control in case this function is called in the - // context of a CONE event handler such as - // CCoeControl::ProcessPointerEventL - QMetaObject::invokeMethod(q, "_q_delayedDestroy", - Qt::QueuedConnection, Q_ARG(WId, destroyw)); - } - - if (q->testAttribute(Qt::WA_AcceptTouchEvents)) - registerTouchWindow(); -} - - -void QWidgetPrivate::show_sys() -{ - Q_Q(QWidget); - - if (q->testAttribute(Qt::WA_OutsideWSRange)) - return; - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - q->setAttribute(Qt::WA_Mapped); - - if (q->testAttribute(Qt::WA_DontShowOnScreen)) { - invalidateBuffer(q->rect()); - return; - } - - if (q->internalWinId()) { - if (!extra->activated) - activateSymbianWindow(); - - QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); - const bool isFullscreen = q->windowState() & Qt::WindowFullScreen; - const TBool cbaRequested = q->windowFlags() & Qt::WindowSoftkeysVisibleHint; - -#ifdef Q_WS_S60 - // Lazily initialize the S60 screen furniture when the first window is shown. - if (q->isWindow() && !QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) - && !S60->buttonGroupContainer() && !S60->statusPane()) { - - if (!q->testAttribute(Qt::WA_DontShowOnScreen)) { - - // Create the status pane and CBA here - CEikAppUi *ui = static_cast<CEikAppUi *>(S60->appUi()); - MEikAppUiFactory *factory = CEikonEnv::Static()->AppUiFactory(); - - QT_TRAP_THROWING( - factory->CreateResourceIndependentFurnitureL(ui); - - TRect boundingRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); - - CEikButtonGroupContainer *cba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba, - CEikButtonGroupContainer::EHorizontal,ui,R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); - if (isFullscreen && !cbaRequested) - cba->MakeVisible(false); - - CEikButtonGroupContainer *oldCba = factory->SwapButtonGroup(cba); - Q_ASSERT(!oldCba); - S60->setButtonGroupContainer(cba); - - // If the creation of the first widget is delayed, for example by doing it - // inside the event loop, S60 somehow "forgets" to set the visibility of the - // toolbar (the three middle softkeys) when you flip the phone over, so we - // need to do it ourselves to avoid a "hole" in the application, even though - // Qt itself does not use the toolbar directly.. - CAknAppUi *appui = dynamic_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi()); - if (appui) { - CAknToolbar *toolbar = appui->PopupToolbar(); - if (toolbar && !toolbar->IsVisible()) - toolbar->SetToolbarVisibility(ETrue); - } - - CEikMenuBar *menuBar = new(ELeave) CEikMenuBar; - menuBar->ConstructL(ui, 0, R_AVKON_MENUPANE_EMPTY); - menuBar->SetMenuType(CEikMenuBar::EMenuOptions); - S60->appUi()->AddToStackL(menuBar,ECoeStackPriorityMenu,ECoeStackFlagRefusesFocus); - - CEikMenuBar *oldMenu = factory->SwapMenuBar(menuBar); - Q_ASSERT(!oldMenu); - ) - - if (S60->statusPane()) { - // Use QDesktopWidget as the status pane observer to proxy for the AppUi. - // Can't use AppUi directly because it privately inherits from MEikStatusPaneObserver. - QSymbianControl *desktopControl = static_cast<QSymbianControl *>(QApplication::desktop()->winId()); - S60->statusPane()->SetObserver(desktopControl); - if (isFullscreen) { - const bool cbaVisible = S60->buttonGroupContainer() && S60->buttonGroupContainer()->IsVisible(); - S60->setStatusPaneAndButtonGroupVisibility(false, cbaVisible); - } - } - } - } -#endif - - // Fill client area if maximized OR - // Put window below status pane unless the window has an explicit position. - if (!isFullscreen) { - if (q->windowState() & Qt::WindowMaximized) { - TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); - id->SetExtent(r.iTl, r.Size()); - } else if (!q->testAttribute(Qt::WA_Moved) && q->windowType() != Qt::Dialog) { - id->SetPosition(static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl); - } - } - - id->MakeVisible(true); - - if(q->isWindow()&&!q->testAttribute(Qt::WA_ShowWithoutActivating)) - id->setFocusSafely(true); - } - - invalidateBuffer(q->rect()); -} - -void QWidgetPrivate::activateSymbianWindow(WId wid) -{ - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - Q_ASSERT(q->testAttribute(Qt::WA_Mapped)); - Q_ASSERT(!extra->activated); - - if(!wid) - wid = q->internalWinId(); - - Q_ASSERT(wid); - - QT_TRAP_THROWING(wid->ActivateL()); - extra->activated = 1; -} - -void QWidgetPrivate::hide_sys() -{ - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - deactivateWidgetCleanup(); - QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); - - if (id) { - //Incorrect optimization - for popup windows, Qt's focus is moved before - //hide_sys is called, resulting in the popup window keeping its elevated - //position in the CONE control stack. - //This can result in keyboard focus being in an invisible widget in some - //conditions - e.g. QTBUG-4733 - //if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->setFocusSafely(false); - id->MakeVisible(false); - if (QWidgetBackingStore *bs = maybeBackingStore()) - bs->releaseBuffer(); - } else { - invalidateBuffer(q->rect()); - } - - q->setAttribute(Qt::WA_Mapped, false); -} - -void QWidgetPrivate::setFocus_sys() -{ - Q_Q(QWidget); - if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup) - if (!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged() - static_cast<QSymbianControl *>(q->effectiveWinId())->setFocusSafely(true); -} - -void QWidgetPrivate::raise_sys() -{ - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) { - q->internalWinId()->DrawableWindow()->SetOrdinalPosition(0); - - // If toplevel widget, raise app to foreground - if (q->isWindow()) - S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup(q).Identifier(), 0); - } -} - -void QWidgetPrivate::lower_sys() -{ - Q_Q(QWidget); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) { - // If toplevel widget, lower app to background - if (q->isWindow()) - S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup(q).Identifier(), -1); - else - q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1); - } - - if (!q->isWindow()) - invalidateBuffer(q->rect()); -} - -void QWidgetPrivate::setModal_sys() -{ - -} - -void QWidgetPrivate::stackUnder_sys(QWidget* w) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (q->internalWinId() && w->internalWinId()) { - RDrawableWindow *const thisWindow = q->internalWinId()->DrawableWindow(); - RDrawableWindow *const otherWindow = w->internalWinId()->DrawableWindow(); - thisWindow->SetOrdinalPosition(otherWindow->OrdinalPosition() + 1); - } - - if (!q->isWindow() || !w->internalWinId()) - invalidateBuffer(q->rect()); -} - -void QWidgetPrivate::reparentChildren() -{ - Q_Q(QWidget); - - QObjectList chlist = q->children(); - for (int i = 0; i < chlist.size(); ++i) { // reparent children - QObject *obj = chlist.at(i); - if (obj->isWidgetType()) { - QWidget *w = (QWidget *)obj; - if (!w->testAttribute(Qt::WA_WState_Created)) - continue; - if (!w->isWindow()) { - w->d_func()->invalidateBuffer(w->rect()); - WId parent = q->effectiveWinId(); - WId child = w->effectiveWinId(); - if (parent != child) { - // Child widget is native. Because Symbian windows cannot be - // re-parented, we must re-create the window. - const WId window = 0; - const bool initializeWindow = false; - const bool destroyOldWindow = true; - w->d_func()->create_sys(window, initializeWindow, destroyOldWindow); - } - // ### TODO: We probably also need to update the component array here - w->d_func()->reparentChildren(); - } else { - bool showIt = w->isVisible(); - QPoint old_pos = w->pos(); - w->setParent(q, w->windowFlags()); - w->move(old_pos); - if (showIt) - w->show(); - } - } - } -} - -void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) -{ - Q_Q(QWidget); - - if (parent && parent->windowType() == Qt::Desktop) { - symbianScreenNumber = qt_widget_private(parent)->symbianScreenNumber; - parent = 0; - } - - bool wasCreated = q->testAttribute(Qt::WA_WState_Created); - - if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(q->geometry()); - - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - q->setAttribute(Qt::WA_DropSiteRegistered, false); - - QSymbianControl *old_winid = static_cast<QSymbianControl *>(wasCreated ? data.winid : 0); - if ((q->windowType() == Qt::Desktop)) - old_winid = 0; - - // old_winid may not have received a 'not visible' visibility - // changed event before being destroyed; make sure that it is - // removed from the backing store's list of visible windows. - if (old_winid) - S60->controlVisibilityChanged(old_winid, false); - - setWinId(0); - - // hide and reparent our own window away. Otherwise we might get - // destroyed when emitting the child remove event below. See QWorkspace. - if (wasCreated && old_winid) { - old_winid->MakeVisible(false); - if (old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged() - old_winid->setFocusSafely(false); - old_winid->SetParent(0); - } - - QObjectPrivate::setParent_helper(parent); - bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); - - data.window_flags = f; - data.fstrut_dirty = true; - q->setAttribute(Qt::WA_WState_Created, false); - q->setAttribute(Qt::WA_WState_Visible, false); - q->setAttribute(Qt::WA_WState_Hidden, false); - adjustFlags(data.window_flags, q); - // keep compatibility with previous versions, we need to preserve the created state - // (but we recreate the winId for the widget being reparented, again for compatibility) - if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) - createWinId(); - if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) - q->setAttribute(Qt::WA_WState_Hidden); - q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); - - if (wasCreated) - reparentChildren(); - - if (old_winid) { - CBase::Delete(old_winid); - } - - if (q->testAttribute(Qt::WA_AcceptDrops) - || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) - q->setAttribute(Qt::WA_DropSiteRegistered, true); - - invalidateBuffer(q->rect()); -} - -void QWidgetPrivate::setConstraints_sys() -{ - -} - - -void QWidgetPrivate::s60UpdateIsOpaque() -{ - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - - const bool writeAlpha = extraData()->nativePaintMode == QWExtra::BlitWriteAlpha; - if (!q->testAttribute(Qt::WA_TranslucentBackground) && !writeAlpha) - return; - const bool requireAlphaChannel = !isOpaque || writeAlpha; - - createTLExtra(); - - RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); - -#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE - if (QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { - window->SetSurfaceTransparency(!isOpaque); - extra->topextra->nativeWindowTransparencyEnabled = !isOpaque; - return; - } -#endif - if (requireAlphaChannel) { - const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA)); - if (window->SetTransparencyAlphaChannel() == KErrNone) { - window->SetBackgroundColor(TRgb(255, 255, 255, 0)); - extra->topextra->nativeWindowTransparencyEnabled = 1; - if (extra->topextra->backingStore.data() && ( - QApplicationPrivate::graphics_system_name == QLatin1String("openvg") - || QApplicationPrivate::graphics_system_name == QLatin1String("opengl"))) { - // Semi-transparent EGL surfaces aren't supported. We need to - // recreate backing store to get translucent surface (raster surface). - extra->topextra->backingStore.create(q); - extra->topextra->backingStore.registerWidget(q); - // FixNativeOrientation() will not work without an EGL surface. - q->setAttribute(Qt::WA_SymbianNoSystemRotation, false); - } - } - } else if (extra->topextra->nativeWindowTransparencyEnabled) { - window->SetTransparentRegion(TRegionFix<1>()); - extra->topextra->nativeWindowTransparencyEnabled = 0; - } -} - -void QWidgetPrivate::setWindowIcon_sys(bool forceReset) -{ -#ifdef Q_WS_S60 - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() ) - return; - - QTLWExtra* topData = this->topData(); - if (topData->iconPixmap && !forceReset) - // already been set - return; - - TRect cPaneRect; - TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect ); - CAknContextPane* contextPane = S60->contextPane(); - if (found && contextPane) { // We have context pane with valid metrics - QIcon icon = q->windowIcon(); - if (!icon.isNull()) { - // Valid icon -> set it as an context pane picture - QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight)); - QPixmap pm = icon.pixmap(size); - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); - CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); - contextPane->SetPicture(nBitmap,nMask); - } else { - // Icon set to null -> set context pane picture to default - QT_TRAP_THROWING(contextPane->SetPictureToDefaultL()); - } - } else { - // Context pane does not exist, try setting small icon to title pane - TRect titlePaneRect; - TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect ); - CAknTitlePane* titlePane = S60->titlePane(); - if (found && titlePane) { // We have title pane with valid metrics - // The API to get title_pane graphics size is not public -> assume square space based - // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since - // then title pane would automatically scale the bitmap. Unfortunately it is not public API - // Also this function is leaving, although it is not named as such. - const CFont * font; - QT_TRAP_THROWING(font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont)); - TSize iconSize(font->HeightInPixels(), font->HeightInPixels()); - - QIcon icon = q->windowIcon(); - if (!icon.isNull()) { - // Valid icon -> set it as an title pane small picture - QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight)); - QPixmap pm = icon.pixmap(size); - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); - CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); - titlePane->SetSmallPicture( nBitmap, nMask, ETrue ); - } else { - // Icon set to null -> set context pane picture to default - titlePane->SetSmallPicture( NULL, NULL, EFalse ); - } - } - } - -#else - Q_UNUSED(forceReset) -#endif -} - -void QWidgetPrivate::setWindowTitle_sys(const QString &caption) -{ -#ifdef Q_WS_S60 - Q_Q(QWidget); - if (q->isWindow()) { - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - CAknTitlePane* titlePane = S60->titlePane(); - if (titlePane) { - if (caption.isEmpty()) { - QT_TRAP_THROWING(titlePane->SetTextToDefaultL()); - } else { - QT_TRAP_THROWING(titlePane->SetTextL(qt_QString2TPtrC(caption))); - } - } - } -#else - Q_UNUSED(caption) -#endif -} - -void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */) -{ - -} - -void QWidgetPrivate::scroll_sys(int dx, int dy) -{ - Q_Q(QWidget); - - scrollChildren(dx, dy); - if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) { - scrollRect(q->rect(), dx, dy); - } else { - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - RDrawableWindow *const window = q->internalWinId()->DrawableWindow(); - window->Scroll(TPoint(dx, dy)); - } -} - -void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) -{ - Q_Q(QWidget); - - if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) { - scrollRect(r, dx, dy); - } else { - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - RDrawableWindow *const window = q->internalWinId()->DrawableWindow(); - window->Scroll(TPoint(dx, dy), qt_QRect2TRect(r)); - } -} - -/*! - For this function to work in the emulator, you must add: - TRANSPARENCY - To a line in the wsini.ini file. -*/ -void QWidgetPrivate::setWindowOpacity_sys(qreal) -{ - // ### TODO: Implement uniform window transparency -} - -void QWidgetPrivate::updateFrameStrut() -{ - -} - -void QWidgetPrivate::updateSystemBackground() -{ - -} - -void QWidgetPrivate::registerDropSite(bool /* on */) -{ - -} - -void QWidgetPrivate::createTLSysExtra() -{ - extra->topextra->inExpose = 0; - extra->topextra->nativeWindowTransparencyEnabled = 0; -} - -void QWidgetPrivate::deleteTLSysExtra() -{ - extra->topextra->backingStore.destroy(); -} - -void QWidgetPrivate::createSysExtra() -{ - extra->activated = 0; - extra->nativePaintMode = QWExtra::Default; - extra->receiveNativePaintEvents = 0; -} - -void QWidgetPrivate::deleteSysExtra() -{ - // this should only be non-zero if destroy() has not run due to constructor fail - if (data.winid) { - data.winid->ControlEnv()->AppUi()->RemoveFromStack(data.winid); - delete data.winid; - data.winid = 0; - } -} - -QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() -{ - return new QS60WindowSurface(q_func()); -} - -void QWidgetPrivate::setMask_sys(const QRegion& /* region */) -{ - -} - -void QWidgetPrivate::registerTouchWindow() -{ -#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER - Q_Q(QWidget); - if (q->testAttribute(Qt::WA_WState_Created) && q->windowType() != Qt::Desktop) { - RWindow *rwindow = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); - QSymbianControl *window = static_cast<QSymbianControl *>(q->effectiveWinId()); - //Enabling advanced pointer events for controls that already have active windows causes a panic. - if (!window->isControlActive()) - rwindow->EnableAdvancedPointers(); - } -#endif -} - -int QWidget::metric(PaintDeviceMetric m) const -{ - Q_D(const QWidget); - int val; - if (m == PdmWidth) { - val = data->crect.width(); - } else if (m == PdmHeight) { - val = data->crect.height(); - } else { - CWsScreenDevice *scr = S60->screenDevice(this); - switch(m) { - case PdmDpiX: - case PdmPhysicalDpiX: - if (d->extra && d->extra->customDpiX) { - val = d->extra->customDpiX; - } else { - const QWidgetPrivate *p = d; - while (p->parent) { - p = static_cast<const QWidget *>(p->parent)->d_func(); - if (p->extra && p->extra->customDpiX) { - val = p->extra->customDpiX; - break; - } - } - if (p == d || !(p->extra && p->extra->customDpiX)) - val = S60->defaultDpiX; - } - break; - case PdmDpiY: - case PdmPhysicalDpiY: - if (d->extra && d->extra->customDpiY) { - val = d->extra->customDpiY; - } else { - const QWidgetPrivate *p = d; - while (p->parent) { - p = static_cast<const QWidget *>(p->parent)->d_func(); - if (p->extra && p->extra->customDpiY) { - val = p->extra->customDpiY; - break; - } - } - if (p == d || !(p->extra && p->extra->customDpiY)) - val = S60->defaultDpiY; - } - break; - case PdmWidthMM: - { - TInt twips = scr->HorizontalPixelsToTwips(data->crect.width()); - val = (int)(twips * (25.4/KTwipsPerInch)); - break; - } - case PdmHeightMM: - { - TInt twips = scr->VerticalPixelsToTwips(data->crect.height()); - val = (int)(twips * (25.4/KTwipsPerInch)); - break; - } - case PdmNumColors: - val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode()); - break; - case PdmDepth: - val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode()); - break; - default: - val = 0; - qWarning("QWidget::metric: Invalid metric command"); - } - } - return val; -} - -QPaintEngine *QWidget::paintEngine() const -{ - return 0; -} - -QPoint QWidget::mapToGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { - - QPoint p = pos + data->crect.topLeft(); - return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p); - - } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel - QPoint tp = geometry().topLeft(); - return pos + tp; - } - - // Native window case - const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen(); - const QPoint globalPos = QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY) + pos; - return globalPos; -} - -QPoint QWidget::mapFromGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { - QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos); - return p - data->crect.topLeft(); - } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel - QPoint tp = geometry().topLeft(); - return pos - tp; - } - - // Native window case - const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen(); - const QPoint widgetPos = pos - QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY); - return widgetPos; -} - -static Qt::WindowStates effectiveState(Qt::WindowStates state) -{ - if (state & Qt::WindowMinimized) - return Qt::WindowMinimized; - else if (state & Qt::WindowFullScreen) - return Qt::WindowFullScreen; - else if (state & Qt::WindowMaximized) - return Qt::WindowMaximized; - return Qt::WindowNoState; -} - -void QWidget::setWindowState(Qt::WindowStates newstate) -{ - Q_D(QWidget); - - Qt::WindowStates oldstate = windowState(); - - const TBool isFullscreen = newstate & Qt::WindowFullScreen; -#ifdef Q_WS_S60 - const TBool cbaRequested = windowFlags() & Qt::WindowSoftkeysVisibleHint; - const TBool cbaVisible = CEikButtonGroupContainer::Current() ? true : false; - const TBool softkeyVisibilityChange = isFullscreen && (cbaRequested != cbaVisible); - - if (oldstate == newstate && !softkeyVisibilityChange) - return; -#endif // Q_WS_S60 - - if (isWindow()) { - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - - const bool wasResized = testAttribute(Qt::WA_Resized); - const bool wasMoved = testAttribute(Qt::WA_Moved); - - QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId()); - if (window && newstate & Qt::WindowMinimized) { - window->setFocusSafely(false); - window->MakeVisible(false); - } else if (window && oldstate & Qt::WindowMinimized) { - window->setFocusSafely(true); - window->MakeVisible(true); - } - -#ifdef Q_WS_S60 - // The window decoration visibility has to be changed before doing actual window state - // change since in that order the availableGeometry will return directly the right size and - // we will avoid unnecessary redraws - bool decorationsVisible = S60->setRecursiveDecorationsVisibility(this, newstate); -#endif // Q_WS_S60 - - // Ensure the initial size is valid, since we store it as normalGeometry below. - if (!wasResized && !isVisible()) - adjustSize(); - - QTLWExtra *top = d->topData(); - QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; - - const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint; - if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) { - setAttribute(Qt::WA_OutsideWSRange, false); - if (d->symbianScreenNumber > 0) { - int w = S60->screenWidthInPixelsForScreen[d->symbianScreenNumber]; - int h = S60->screenHeightInPixelsForScreen[d->symbianScreenNumber]; - if (w <= 0 || h <= 0) - window->SetExtentToWholeScreen(); - else - window->SetExtent(TPoint(0, 0), TSize(w, h)); - } else { - window->SetExtentToWholeScreen(); - } - } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) { - setAttribute(Qt::WA_OutsideWSRange, false); - TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this)); - window->SetExtent(maxExtent.iTl, maxExtent.Size()); - } else { -#ifdef Q_WS_S60 - // With delayed creation of S60 app panes, the normalGeometry calculated above is not - // accurate because it did not consider the status pane. This means that when returning - // normal mode after showing the status pane, the geometry would overlap so we should - // move it if it never had an explicit position. - if (!wasMoved && S60->statusPane() && decorationsVisible) { - TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl; - normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); - } -#endif - setGeometry(normalGeometry); - } - - //restore normal geometry - top->normalGeometry = normalGeometry; - - // FixMe QTBUG-8977 - // In some platforms, WA_Resized and WA_Moved are also not set when application window state is - // anything else than normal. In Symbian we can restore them only for normal window state since - // restoring for other modes, will make fluidlauncher to be launched in wrong size (200x100) - if (effectiveState(newstate) == Qt::WindowNoState) { - setAttribute(Qt::WA_Resized, wasResized); - setAttribute(Qt::WA_Moved, wasMoved); - } - } - - data->window_state = newstate; - - if (newstate & Qt::WindowActive) - activateWindow(); - - if (isWindow()) { - // Now that the new state is set, fix the display memory layout, if needed. - QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId()); - window->ensureFixNativeOrientation(); - } - - QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); -} - - -void QWidget::destroy(bool destroyWindow, bool destroySubWindows) -{ - Q_D(QWidget); - d->aboutToDestroy(); - if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(geometry()); - d->deactivateWidgetCleanup(); - QSymbianControl *id = static_cast<QSymbianControl *>(internalWinId()); - if (testAttribute(Qt::WA_WState_Created)) { - -#ifndef QT_NO_IM - if (d->ic) { - delete d->ic; - } else { - QInputContext *ic = QApplicationPrivate::inputContext; - if (ic) { - ic->widgetDestroyed(this); - } - } -#endif - - if (QWidgetPrivate::mouseGrabber == this) - releaseMouse(); - if (QWidgetPrivate::keyboardGrabber == this) - releaseKeyboard(); - setAttribute(Qt::WA_WState_Created, false); - QObjectList childList = children(); - for (int i = 0; i < childList.size(); ++i) { // destroy all widget children - register QObject *obj = childList.at(i); - if (obj->isWidgetType()) - static_cast<QWidget*>(obj)->destroy(destroySubWindows, - destroySubWindows); - } - if (destroyWindow && !(windowType() == Qt::Desktop) && id) { - if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged() - id->setFocusSafely(false); - id->ControlEnv()->AppUi()->RemoveFromStack(id); - } - } - - QT_TRY { - d->setWinId(0); - } QT_CATCH (const std::bad_alloc &) { - // swallow - destructors must not throw - } - - if (destroyWindow) { - delete id; - // At this point the backing store should already be destroyed - // so we flush the command buffer to ensure that the freeing of - // those resources and deleting the window can happen "atomically" - if (qApp) - S60->wsSession().Flush(); - } -} - -QWidget *QWidget::mouseGrabber() -{ - return QWidgetPrivate::mouseGrabber; -} - -QWidget *QWidget::keyboardGrabber() -{ - return QWidgetPrivate::keyboardGrabber; -} - -void QWidget::grabKeyboard() -{ - if (!qt_nograb()) { - if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this) - QWidgetPrivate::keyboardGrabber->releaseKeyboard(); - - // ### TODO: Native keyboard grab - - QWidgetPrivate::keyboardGrabber = this; - } -} - -void QWidget::releaseKeyboard() -{ - if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) { - // ### TODO: Native keyboard release - QWidgetPrivate::keyboardGrabber = 0; - } -} - -void QWidget::grabMouse() -{ - if (isVisible() && !qt_nograb()) { - if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) - QWidgetPrivate::mouseGrabber->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - WId id = effectiveWinId(); - id->SetPointerCapture(true); - QWidgetPrivate::mouseGrabber = this; - -#ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(cursor()); -#endif - } -} - -#ifndef QT_NO_CURSOR -void QWidget::grabMouse(const QCursor &cursor) -{ - if (isVisible() && !qt_nograb()) { - if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) - QWidgetPrivate::mouseGrabber->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - WId id = effectiveWinId(); - id->SetPointerCapture(true); - QWidgetPrivate::mouseGrabber = this; - - QApplication::setOverrideCursor(cursor); - } -} -#endif - -void QWidget::releaseMouse() -{ - if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) { - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if(!window()->isModal()) { - WId id = effectiveWinId(); - id->SetPointerCapture(false); - } - QWidgetPrivate::mouseGrabber = 0; -#ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); -#endif - } -} - -void QWidget::activateWindow() -{ - Q_D(QWidget); - - QWidget *tlw = window(); - if (tlw->isVisible()) { - window()->createWinId(); - QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId()); - if (!id->IsFocused()) - id->setFocusSafely(true); - } -} - -#ifndef QT_NO_CURSOR - -void QWidgetPrivate::setCursor_sys(const QCursor &cursor) -{ - Q_UNUSED(cursor); - Q_Q(QWidget); - qt_symbian_set_cursor(q, false); -} - -void QWidgetPrivate::unsetCursor_sys() -{ - Q_Q(QWidget); - qt_symbian_set_cursor(q, false); -} -#endif - -QT_END_NAMESPACE |