--- a/src/gui/kernel/qapplication_s60.cpp Fri Sep 17 08:34:18 2010 +0300
+++ b/src/gui/kernel/qapplication_s60.cpp Mon Oct 04 01:19:32 2010 +0300
@@ -87,6 +87,10 @@
#include <hal.h>
#include <hal_data.h>
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+#include <graphics/wstfxconst.h>
+#endif
+
QT_BEGIN_NAMESPACE
// Goom Events through Window Server
@@ -112,6 +116,63 @@
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();
+}
+#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 {
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ S60->wsSession().SendEffectCommand(ETfxCmdRestoreLayer);
+#endif
+ backingStore.create(window);
+ backingStore.registerWidget(widget);
+ qt_widget_private(widget)->invalidateBuffer(widget->rect());
+ widget->repaint();
+ }
+ } else {
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ S60->wsSession().SendEffectCommand(ETfxCmdDeallocateLayer);
+#endif
+ 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)
@@ -207,8 +268,6 @@
}
-QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
-
static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
{
Qt::KeyboardModifiers result = Qt::NoModifier;
@@ -355,7 +414,7 @@
{
if (!desktop)
{
- if (isWindowOwning or !qwidget->parentWidget())
+ if (isWindowOwning || !qwidget->parentWidget())
CreateWindowL(S60->windowGroup());
else
/**
@@ -378,10 +437,42 @@
DrawableWindow()->SetPointerGrab(ETrue);
}
+
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_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())
+ ? 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) {
@@ -621,251 +712,302 @@
TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
{
- switch (type) {
- //case EEventKeyDown: // <-- Intentionally left out. See below.
- case EEventKeyUp:
- case EEventKey:
- {
+ /*
+ 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) ||
+ 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)
- 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;
- TPoint epos(x, y);
- TPoint cpos = epos - PositionRelativeToScreen();
- fakeEvent.iPosition = cpos;
- fakeEvent.iParentPosition = epos;
- if(fakeEvent.iType != -1)
- HandlePointerEvent(fakeEvent);
- return EKeyWasConsumed;
- }
- }
-#endif
- // S60 has a confusing way of delivering key events. There are three types of
- // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the
- // two first events are generated. When releasing the key, the last one is
- // generated.
- // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events,
- // we need to do some special tricks to map it to the Qt way. First, we completely
- // discard EKeyEventDown events, since they are redundant. Second, since
- // EKeyEventUp does not give us a keysym, we need to cache the keysyms from
- // the EKeyEvent events. This is what resolveS60ScanCode does.
-
-
- // ### hackish way to send Qt application to background when pressing right softkey
- /*
- if( keyEvent.iScanCode == EStdKeyDevice1 ) {
- S60->window_group->SetOrdinalPosition(-1);
- qApp->setActiveWindow(0);
- return EKeyWasNotConsumed;
- }
- */
-
- 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 == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
- mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
- (keyEvent.iRepeats != 0), 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
-// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
-// if (!wid)
-// Could happen if window isn't shown yet.
-// return EKeyWasNotConsumed;
- 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;
+ 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;
+ }
- 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;
+ 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)
+ 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;
+ TPoint epos(x, y);
+ TPoint cpos = epos - PositionRelativeToScreen();
+ fakeEvent.iPosition = cpos;
+ fakeEvent.iParentPosition = epos;
+ if(fakeEvent.iType != -1)
+ HandlePointerEvent(fakeEvent);
+ return EKeyWasConsumed;
}
- return sendKeyEvent(widget, &qKeyEvent);
}
- }
+#endif
+
return EKeyWasNotConsumed;
}
@@ -963,7 +1105,7 @@
if (QApplicationPrivate::runtime_graphics_system) {
QRuntimeWindowSurface *rtSurface =
static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface());
- s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface);
+ s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface.data());
} else
#endif
s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
@@ -971,19 +1113,22 @@
CFbsBitmap *bitmap = s60Surface->symbianBitmap();
CWindowGc &gc = SystemGc();
- switch(qwidget->d_func()->extraData()->nativePaintMode) {
+ 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:
if (qwidget->d_func()->isOpaque)
gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect);
break;
-
case QWExtra::ZeroFill:
- if (Window().DisplayMode() == EColor16MA) {
+ if (Window().DisplayMode() == EColor16MA
+ || Window().DisplayMode() == Q_SYMBIAN_ECOLOR16MAP) {
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
gc.SetBrushColor(TRgb::Color16MA(0));
@@ -993,7 +1138,6 @@
gc.Clear(controlRect);
};
break;
-
default:
Q_ASSERT(false);
}
@@ -1096,30 +1240,36 @@
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
#ifdef Q_WS_S60
// If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
- CEikStatusPane *statusPane = S60->statusPane();
- CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer();
- TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
- if (statusPane)
- statusPane->MakeVisible(visible);
- if (buttonGroup) {
- // Visibility
- const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
- const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
- buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint));
- }
+ const bool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ const bool statusPaneVisibility = visible;
+ const bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
+ const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint));
+ S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility);
#endif
} else if (QApplication::activeWindow() == qwidget->window()) {
- if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog() || S60->menuBeingConstructed) {
- QWidget *fw = QApplication::focusWidget();
- if (fw) {
- QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
- QCoreApplication::sendEvent(fw, &event);
+ 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;
}
- m_symbianPopupIsOpen = true;
- return;
+
+ QApplication::setActiveWindow(0);
}
-
- QApplication::setActiveWindow(0);
}
// else { We don't touch the active window unless we were explicitly activated or deactivated }
}
@@ -1211,6 +1361,11 @@
}
}
+bool QSymbianControl::isControlActive()
+{
+ return IsActivated() ? true : false;
+}
+
/*!
\typedef QApplication::QS60MainApplicationFactory
\since 4.6
@@ -1261,7 +1416,7 @@
// framework destruction.
TTrapHandler *origTrapHandler = User::TrapHandler();
- // The S60 framework has not been initalized. We need to do it.
+ // The S60 framework has not been initialized. We need to do it.
TApaApplicationFactory factory(S60->s60ApplicationFactory ?
S60->s60ApplicationFactory : newS60Application);
CApaCommandLine* commandLine = 0;
@@ -1375,6 +1530,8 @@
S60->avkonComponentsSupportTransparency = (value==1) ? true : false;
}
}
+ delete repository;
+ repository = 0;
#endif
#ifdef QT_KEYPAD_NAVIGATION
@@ -1416,6 +1573,10 @@
systemFont.setFamily(systemFont.defaultFamily());
QApplicationPrivate::setSystemFont(systemFont);
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ QObject::connect(qApp, SIGNAL(aboutToQuit()), qApp, SLOT(_q_aboutToQuit()));
+#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;
@@ -1439,7 +1600,7 @@
*/
// Register WId with the metatype system. This is to enable
- // QWidgetPrivate::create_sys to used delayed slot invokation in order
+ // QWidgetPrivate::create_sys to used delayed slot invocation in order
// to destroy WId objects during reparenting.
qRegisterMetaType<WId>("WId");
}
@@ -1505,6 +1666,9 @@
void QApplicationPrivate::enterModal_sys(QWidget *widget)
{
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeEnter);
+#endif
if (widget) {
static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(ETrue);
// Modal partial screen dialogs (like queries) capture pointer events.
@@ -1520,6 +1684,9 @@
void QApplicationPrivate::leaveModal_sys(QWidget *widget)
{
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ S60->wsSession().SendEffectCommand(ETfxCmdAppModalModeExit);
+#endif
if (widget) {
static_cast<QSymbianControl *>(widget->effectiveWinId())->FadeBehindPopup(EFalse);
// ### FixMe: Add specialized behaviour for fullscreen modal dialogs
@@ -1810,27 +1977,10 @@
if (callSymbianEventFilters(symbianEvent))
return 1;
const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
- QWidget *w = QWidgetPrivate::mapper->value(control);
- QWidget *const window = w->window();
- if (!window->d_func()->maybeTopData())
- break;
- QRefCountedWidgetBackingStore &backingStore = window->d_func()->maybeTopData()->backingStore;
- if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
- backingStore.widgetHidden(w);
- // In order to ensure that any resources used by the window surface
- // are immediately freed, we flush the WSERV command buffer.
- S60->wsSession().Flush();
- } else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) {
- if (backingStore.data()) {
- backingStore.widgetShown(w);
- } else {
- // Create backing store with an initial reference count of 1
- backingStore.create(window);
- backingStore.widgetShown(w);
- w->d_func()->invalidateBuffer(w->rect());
- w->repaint();
- }
- }
+ if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible)
+ S60->controlVisibilityChanged(control, false);
+ else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
+ S60->controlVisibilityChanged(control, true);
return 1;
}
break;
@@ -1884,13 +2034,6 @@
if (switchToSwRendering) {
QRuntimeGraphicsSystem *gs =
static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
-
- uint memoryUsage = gs->memoryUsage();
- uint memoryForFullscreen = ( S60->screenDepth / 8 )
- * S60->screenWidthInPixels
- * S60->screenHeightInPixels;
-
- S60->memoryLimitForHwRendering = memoryUsage - memoryForFullscreen;
gs->setGraphicsSystem(QLatin1String("raster"));
}
}
@@ -1906,8 +2049,7 @@
if(QApplicationPrivate::runtime_graphics_system) {
QRuntimeGraphicsSystem *gs =
static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
- gs->setGraphicsSystem(QLatin1String("openvg"), S60->memoryLimitForHwRendering);
- S60->memoryLimitForHwRendering = 0;
+ gs->setGraphicsSystem(QLatin1String("openvg"));
}
#endif
break;
@@ -2076,13 +2218,18 @@
TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
{
+ if (!scanCode)
+ return keysym;
+
+ QApplicationPrivate *d = QApplicationPrivate::instance();
+
if (keysym) {
// If keysym is specified, cache it.
- scanCodeCache.insert(scanCode, keysym);
+ d->scanCodeCache.insert(scanCode, keysym);
return keysym;
} else {
// If not, retrieve the cached version.
- return scanCodeCache[scanCode];
+ return d->scanCodeCache[scanCode];
}
}
@@ -2202,6 +2349,14 @@
#endif // QT_NO_CURSOR
+void QApplicationPrivate::_q_aboutToQuit()
+{
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+ // Send the shutdown tfx command
+ S60->wsSession().SendEffectCommand(ETfxCmdAppShutDown);
+#endif
+}
+
QS60ThreadLocalData::QS60ThreadLocalData()
{
CCoeEnv *env = CCoeEnv::Static();