diff -r 10e98eab6f85 -r a359256acfc6 webengine/osswebengine/WebKit/s60/webview/WebView.cpp --- a/webengine/osswebengine/WebKit/s60/webview/WebView.cpp Fri Jul 03 15:54:40 2009 +0100 +++ b/webengine/osswebengine/WebKit/s60/webview/WebView.cpp Thu Aug 27 07:44:59 2009 +0300 @@ -97,9 +97,10 @@ #include "WebPageFullScreenHandler.h" #include "eikon.hrh" #include "WebScrollbarDrawer.h" - +#include "EventNames.h" using namespace WebCore; +using namespace EventNames; const int KRepaintDelayLoading = 500*1000; // dont do repaints more often than this during loading (0.5s) const int KRepaintDelayComplete = 100*1000; // faster updates after load so dynamic scripts etc have better frame rate (0.1s) @@ -193,6 +194,7 @@ , m_ptrbuffer(0) , m_showCursor(false) , m_allowRepaints(true) +, m_prevEditMode(false) { } @@ -536,7 +538,8 @@ // draw to back buffer - + if(m_widgetextension && !IsVisible()) + return; if(!( m_widgetextension && m_widgetextension->IsWidgetPublising())) { mainFrame()->frameView()->draw( *m_webcorecontext, rect ); if ( zoomLevel < m_minZoomLevel ) zoomLevel = m_minZoomLevel; @@ -579,7 +582,8 @@ } layoutPending = false; } - if (!layoutPending) { + + if ( !layoutPending || !isLoading()) { bool needsDraw = false; m_repaints.Tidy(); for (int i=0; iSize(), StaticObjectsContainer::instance()->webSurface()->displayMode()); + if( m_widgetextension && m_widgetextension->IsWidgetPublising()) { + if ( snapshot.Handle() == 0) { + // Create bitmap only once + (snapshot).Create(m_brctl->Size(), StaticObjectsContainer::instance()->webSurface()->displayMode()); + } + CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( &snapshot); + CleanupStack::PushL(device); + + WebCoreGraphicsContext* gc = WebCoreGraphicsContext::NewL( device, &snapshot, mainFrame()->frameView()); + CleanupStack::PushL(gc); + + if( snapshot.Handle() != 0 ) { + // Clear previous offscreen bitmap + // frameView->draw might clear the bitmap. + gc->gc().Clear(); + } + if (snapshot.SizeInPixels()!=m_brctl->Size()) { + snapshot.Resize(m_brctl->Size()); + } + mainFrame()->frameView()->draw( *gc, mainFrame()->frameView()->visibleRect() ); + + CleanupStack::PopAndDestroy(2); } - CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( &snapshot); - CleanupStack::PushL(device); - - WebCoreGraphicsContext* gc = WebCoreGraphicsContext::NewL( device, &snapshot, mainFrame()->frameView()); - CleanupStack::PushL(gc); - - if( snapshot.Handle() != 0 ){ - // Clear previous offscreen bitmap - // frameView->draw might clear the bitmap. - gc->gc().Clear(); - } else if (snapshot.SizeInPixels()!=m_brctl->Size()){ - snapshot.Resize(m_brctl->Size()); - } - mainFrame()->frameView()->draw( *gc, mainFrame()->frameView()->visibleRect() ); - - CleanupStack::PopAndDestroy(2); } @@ -827,17 +834,21 @@ bool WebView::isNaviKey(const TKeyEvent& keyevent) { return ( keyevent.iCode == EKeyUpArrow // North + || keyevent.iCode == EStdKeyUpArrow // : || keyevent.iCode == EKeyRightUpArrow // Northeast - || keyevent.iCode == EStdKeyDevice11 // : Extra KeyEvent supports diagonal event simulator wedge + || keyevent.iCode == EStdKeyDevice11 // : || keyevent.iCode == EKeyRightArrow // East + || keyevent.iCode == EStdKeyRightArrow // : || keyevent.iCode == EKeyRightDownArrow // Southeast - || keyevent.iCode == EStdKeyDevice12 // : Extra KeyEvent supports diagonal event simulator wedge + || keyevent.iCode == EStdKeyDevice12 // : || keyevent.iCode == EKeyDownArrow // South + || keyevent.iCode == EStdKeyDownArrow // : || keyevent.iCode == EKeyLeftDownArrow // Southwest - || keyevent.iCode == EStdKeyDevice13 // : Extra KeyEvent supports diagonal event simulator wedge + || keyevent.iCode == EStdKeyDevice13 // : || keyevent.iCode == EKeyLeftArrow // West + || keyevent.iCode == EStdKeyLeftArrow // : || keyevent.iCode == EKeyLeftUpArrow // Northwest - || keyevent.iCode == EStdKeyDevice10); + || keyevent.iCode == EStdKeyDevice10 ); // : } bool WebView::handleEditable(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame ) @@ -908,11 +919,38 @@ } } +bool WebView::needDeactivateEditable(const TKeyEvent& keyevent, TEventCode eventcode) +{ + bool upOrDown = ((keyevent.iCode == EKeyDevice3) || + (keyevent.iCode == EKeyUpArrow) || + (keyevent.iCode == EStdKeyUpArrow) || + (keyevent.iCode == EKeyRightUpArrow) || + (keyevent.iCode == EKeyDownArrow) || + (keyevent.iCode == EStdKeyDownArrow) || + (keyevent.iCode == EKeyLeftDownArrow)); + bool inEditState = (m_isEditable && (m_focusedElementType == TBrCtlDefs::EElementActivatedInputBox)); + bool isSelectBoxActive = (m_focusedElementType == TBrCtlDefs::EElementSelectBox); + bool deactivateInputBox = (inEditState && upOrDown); + bool deactivateSelectBox = (isSelectBoxActive && isNaviKey(keyevent)); + + return deactivateInputBox || deactivateSelectBox; +} + + +bool WebView::deactivateEditable() +{ + setFocusNone(); + m_prevEditMode = true; + setEditable( EFalse ); + return true; +} + bool WebView::handleEventKeyL(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame) { WebCursor* cursor = StaticObjectsContainer::instance()->webCursor(); bool consumed = false; - + bool tabbedNavigation = (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed); + bool navigationNone = (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone); TKeyEvent oldKeyEvent(m_currentEventKey); oldKeyEvent.iCode = keyevent.iCode; TEventCode oldKeyCode = m_currentEventCode; @@ -920,20 +958,26 @@ m_currentEventKey = keyevent; m_currentEventCode = eventcode; - if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeNone) { + if (navigationNone) { consumed = handleInputElement(keyevent, eventcode, frame); if (!consumed) consumed = sendKeyEventToEngine(keyevent, eventcode, frame); } else { - if (keyevent.iCode == EKeyDevice3) { - // pass it to webcore - sendMouseEventToEngine(TPointerEvent::EButton1Down, - cursor->position(), frame); - - // mimic ccb's behavior of onFocus + if (needDeactivateEditable(keyevent, eventcode)) { + consumed = deactivateEditable(); + handleKeyNavigation(keyevent, eventcode, frame); + } + else if (keyevent.iCode == EKeyDevice3) { + sendMouseEventToEngine(TPointerEvent::EButton1Down, + cursor->position(), frame); + // mimic ccb's behavior of onFocus setFocusedNode(frame); - + if (oldKeyCode == EEventKeyDown && + (m_focusedElementType != TBrCtlDefs::EElementActivatedInputBox)){ + sendKeyEventToEngine(oldKeyEvent, EEventKeyDown, frame); + } + // Toolbar is activated on long key press only if the element // type is EElementNone during EEventKeyDown and EEventKey. // This prevents toolbar from popping up in DHTML pages. Also, @@ -947,32 +991,50 @@ consumed = true; } else if (isNaviKey(keyevent)) { - - if (oldKeyCode == EEventKeyDown){ - // Keydown event is automatically generated before each keypress event, but in this case - // we don't send a keypress event, so send a keydown event explicitly. - downEventConsumed = sendKeyEventToEngine(oldKeyEvent, EEventKeyDown, frame); - } - - - if (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed) { - consumed = downEventConsumed || handleTabbedNavigation(keyevent, eventcode); - } - else { - consumed = handleKeyNavigation(keyevent, eventcode, frame); - } + consumed = handleNaviKeyEvent(oldKeyEvent, oldKeyCode, frame); } // if (m_brctl->settings()->getNavigationType() else { // Not an arrow key.. // activate hovered input element by just start typing - consumed = handleInputElement(keyevent, eventcode, frame); + consumed = !m_isEditable && handleInputElement(keyevent, eventcode, frame); } - if (!consumed && !(m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed && isNaviKey(keyevent))) { + if (!consumed && !(tabbedNavigation && isNaviKey(keyevent))) { consumed = sendKeyEventToEngine(keyevent, eventcode, frame); } } return consumed; } +bool WebView::handleNaviKeyEvent(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame) +{ + bool downEventConsumed = false; + bool consumed = false; + bool tabbedNavigation = (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed); + /* + * For each platform keyDown event EventHandler::keEvent() generates + * keydown and keypress. + * For keypress event we need a char code and since we don't + * have it at the time of EEventKeyDown we pospond it until EEventKey + * and send it here. + */ + if (eventcode == EEventKeyDown){ + downEventConsumed = sendKeyEventToEngine(keyevent, EEventKeyDown, frame); + } + + if (m_isEditable && !downEventConsumed && m_webfeptexteditor->validateTextFormat()) { + setFocusNone(); + } + + if (tabbedNavigation) { + consumed = downEventConsumed || handleTabbedNavigation(m_currentEventKey, m_currentEventCode); + } + else { + consumed = (!m_isEditable && //avoid showing the cursor when we are in the input box + handleKeyNavigation(keyevent, eventcode, frame)) || + downEventConsumed; + } + return consumed; +} + bool WebView::handleInputElement(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame) { @@ -984,16 +1046,18 @@ } else if (m_focusedElementType == TBrCtlDefs::EElementSelectBox || m_focusedElementType == TBrCtlDefs::EElementSelectMultiBox) { - if (m_brctl->settings()->getNavigationType() != SettingsContainer::NavigationTypeNone || keyevent.iCode == EKeyDevice3) { + if (m_brctl->settings()->getNavigationType() != SettingsContainer::NavigationTypeNone || + keyevent.iCode == EKeyDevice3) { sendMousedEvent = true; } } if (sendMousedEvent) { sendMouseEventToEngine(TPointerEvent::EButton1Down, cursor->position(), frame); sendMouseEventToEngine(TPointerEvent::EButton1Up, cursor->position(), frame); - - if (m_focusedElementType == TBrCtlDefs::EElementInputBox || - m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) { + + if (m_focusedElementType == TBrCtlDefs::EElementInputBox || + m_focusedElementType == TBrCtlDefs::EElementTextAreaBox || + m_focusedElementType == TBrCtlDefs::EElementActivatedInputBox) { if (!m_fepTimer) { m_fepTimer = new WebCore::Timer(this, &WebView::fepTimerFired); } @@ -1020,8 +1084,11 @@ if (!cursor->isVisible()) { cursor->cursorUpdate(true); } - - m_savedPosition = mainFrame()->frameView()->contentPos(); + + if(!pageView()) { + m_savedPosition = mainFrame()->frameView()->contentPos(); + } + cursor->scrollAndMoveCursor(keyevent.iCode, m_scrollingSpeed, fastscroll); updateScrollbars(); if (!fastscroll) { @@ -1059,26 +1126,29 @@ int vertical = 0; switch(keyevent.iCode) { case EKeyUpArrow: // North + case EStdKeyUpArrow: // : vertical = -1; break; case EKeyRightUpArrow: // Northeast - case EStdKeyDevice11: // : Extra KeyEvent supports diagonal event simulator wedge + case EStdKeyDevice11: // : vertical = -1; horizontal = +1; break; case EKeyRightArrow: // East + case EStdKeyRightArrow: // : horizontal = +1; break; case EKeyRightDownArrow: // Southeast - case EStdKeyDevice12: // : Extra KeyEvent supports diagonal event simulator wedge + case EStdKeyDevice12: // : vertical = +1; horizontal = +1; break; case EKeyDownArrow: // South + case EStdKeyDownArrow: // : vertical = +1; break; @@ -1089,6 +1159,7 @@ break; case EKeyLeftArrow: // West + case EStdKeyLeftArrow: // : horizontal = -1; break; @@ -1124,26 +1195,47 @@ } } m_pageScrollHandler->scrollbarDrawer()->fadeScrollbar(delay); - - if ( (keyevent.iScanCode == EStdKeyDevice3) || + TKeyEvent correctedKeyEvent(keyevent); + correctedKeyEvent.iCode = correctKeyCode(); + TEventCode eventCodeUp = eventcode; + TEventCode eventCodeDown = EEventKeyDown; + //If we adjusted iCode we have to reset it to 0 after we + //create PlatformKeyEventSymbian when we send the key event. + //Otherwise the character will be drawn twice - by fep editor and by + //WebEditorClient. These two custom eventcodes serves as indicator that + //PlatformKeyEventSymbian::m_symbianEvent.iCode nee to be reset to 0. + if (correctedKeyEvent.iCode != m_currentEventKey.iCode) { + eventCodeDown = (TEventCode)(EEventUser + 1); + eventCodeUp = (TEventCode)(EEventUser + 2); + } + + if ( (keyevent.iScanCode == EStdKeyDevice3) || (keyevent.iScanCode == EStdKeyEnter) ) { - // pass it to webcore - - if (m_focusedElementType == TBrCtlDefs::EElementInputBox || - m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) { - setEditable(true); + // pass it to webcore + + if (( m_focusedElementType == TBrCtlDefs::EElementInputBox || + m_focusedElementType == TBrCtlDefs::EElementTextAreaBox) && + m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed ) { + if (!m_prevEditMode) { + setEditable(true); + } + else { + m_prevEditMode = false; + } } if (m_brctl->settings()->getNavigationType() != SettingsContainer::NavigationTypeNone) { - sendMouseEventToEngine(TPointerEvent::EButton1Up, cursor->position(), frame); + if (!sendKeyEventToEngine(correctedKeyEvent, eventcode, frame)) { + sendMouseEventToEngine(TPointerEvent::EButton1Up, cursor->position(), frame); + } consumed = true; } } if (!consumed) { - - TKeyEvent correctedKeyEvent(keyevent); - correctedKeyEvent.iCode = m_currentEventKey.iCode; - sendKeyEventToEngine(correctedKeyEvent, eventcode, frame); + if (m_currentEventCode == EEventKeyDown) { + sendKeyEventToEngine(correctedKeyEvent, eventCodeDown, frame); + } + sendKeyEventToEngine(correctedKeyEvent, eventCodeUp, frame); } m_currentEventKey = KNullKeyEvent; m_currentEventCode = EEventNull; @@ -1151,11 +1243,55 @@ } -bool WebView::sendKeyEventToEngine(const TKeyEvent& keyevent, +TUint WebView::correctKeyCode() +{ + TUint code = m_currentEventKey.iCode; + // if fep editor was invoked then it consume TKeyEvent and as + // result we have KeyEvent.iCode == 0. So we assume here that + // if element is editable and no iCode in KeyEvent then fep editor + // already put the right character into the input area and we can get + // the correct iCode from the last entered char. + if (m_isEditable && !m_currentEventKey.iCode && m_webfeptexteditor) { + TInt len = m_webfeptexteditor->DocumentLengthForFep(); + if (len > 0) { + TBuf<2> data; + m_webfeptexteditor->GetEditorContentForFep(data, len - 1, 1); + if (data.Length() > 0) { + code = data[0]; + } + } + } + + return code; +} + +bool WebView::sendKeyEventToEngine(const TKeyEvent& keyevent, TEventCode eventcode, Frame* frame) { + bool tabbedNavigation = (m_brctl->settings()->getNavigationType() == SettingsContainer::NavigationTypeTabbed); + Node* targetNode = frame->document()->focusedNode(); + bool hasOnKeyDown = false; + bool hasOnKeyUp = false; + bool hasOnKeyPress = false; + + for (Node* n = targetNode; n; n = n->parentNode()) { + EventTargetNode* tnode = static_cast(n); + hasOnKeyDown = tnode->getHTMLEventListener(keydownEvent); + hasOnKeyUp = tnode->getHTMLEventListener(keyupEvent); + hasOnKeyPress = tnode->getHTMLEventListener(keypressEvent); + if (hasOnKeyDown || hasOnKeyUp || hasOnKeyPress) { + break; + } + } + + + if (!m_isEditable && !(hasOnKeyDown || hasOnKeyUp || hasOnKeyPress)) { + frame->document()->setFocusedNode(NULL); + } bool consumed = frame->eventHandler()->keyEvent(PlatformKeyboardEvent(keyevent,eventcode)); - if (!consumed && eventcode == EEventKey && + frame->document()->setFocusedNode(targetNode); + + if (!consumed && eventcode == EEventKey && (m_brctl->capabilities() & TBrCtlDefs::ECapabilityAccessKeys)) { TKeyEvent ke = keyevent; TChar c(ke.iCode); @@ -1195,27 +1331,19 @@ if (!coreFrame) return EKeyWasNotConsumed; coreFrame = page()->focusController()->focusedOrMainFrame(); - - // edit events - if (m_isEditable) { - consumed = handleEditable(keyevent, eventcode, coreFrame); + + switch( eventcode ) { + case EEventKeyDown: + handleEventKeyDown(keyevent, eventcode, coreFrame); + break; + case EEventKey: + consumed = handleEventKeyL(keyevent, eventcode, coreFrame); + break; + case EEventKeyUp: + consumed = handleEventKeyUp(keyevent, eventcode, coreFrame); + break; } - - // scroll events - if (!consumed) { - switch( eventcode ) { - case EEventKeyDown: - handleEventKeyDown(keyevent, eventcode, coreFrame); - break; - case EEventKey: - if (keyevent.iScanCode != m_currentEventKey.iScanCode ) return EKeyWasNotConsumed; - consumed = handleEventKeyL(keyevent, eventcode, coreFrame); - break; - case EEventKeyUp: - consumed = handleEventKeyUp(keyevent, eventcode, coreFrame); - break; - } - } + return (consumed) ? EKeyWasConsumed : EKeyWasNotConsumed; } @@ -1235,12 +1363,7 @@ scrollDelta.iX *= 100; scrollDelta.iY *= 100; if (!inPageViewMode()) { - if (scrollDelta.iX == 0 && scrollDelta.iY == 0) { - m_pageScrollHandler->scrollbarDrawer()->drawScrollbar(this); - } - else { - m_pageScrollHandler->scrollbarDrawer()->drawScrollbar(this, scrollDelta); - } + m_pageScrollHandler->scrollbarDrawer()->drawScrollbar(this, scrollDelta); } } @@ -1254,6 +1377,7 @@ m_pageView = CPageView::NewL(*this); MakeVisible(EFalse); m_savedPosition = mainFrame()->frameView()->contentPos(); + m_pageViewStartPosition = m_savedPosition; m_brctl->reportStateChanged(TBrCtlDefs::EStateThumbnailView, ETrue); } } @@ -1276,7 +1400,7 @@ if ( m_brctl->capabilities() & TBrCtlDefs::ECapabilityWebKitLite ) return; if (m_pageView) { - mainFrame()->frameView()->scrollTo(m_savedPosition); + mainFrame()->frameView()->scrollTo(m_pageViewStartPosition); closePageView(); } } @@ -1545,6 +1669,8 @@ r.Grow(1, 1); m_repaints.AddRect(r); } + + region.Close(); } else { TRect r(to, bufSize);