diff options
Diffstat (limited to 'Source/WebCore/page')
52 files changed, 1573 insertions, 514 deletions
diff --git a/Source/WebCore/page/BarInfo.idl b/Source/WebCore/page/BarInfo.idl index 2f036c11b..11a97c70e 100644 --- a/Source/WebCore/page/BarInfo.idl +++ b/Source/WebCore/page/BarInfo.idl @@ -29,7 +29,7 @@ module window { interface [ - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] BarInfo { readonly attribute boolean visible; diff --git a/Source/WebCore/page/Console.idl b/Source/WebCore/page/Console.idl index 3c63a8ace..42cd187f9 100644 --- a/Source/WebCore/page/Console.idl +++ b/Source/WebCore/page/Console.idl @@ -29,7 +29,7 @@ module window { interface [ - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] Console { @@ -41,7 +41,7 @@ module window { [CustomArgumentHandling] void dir(); [CustomArgumentHandling] void dirxml(); [V8Custom, CustomArgumentHandling] void trace(); - [V8Custom, CustomArgumentHandling, ImplementationFunction=assertCondition] void assert(in boolean condition); + [V8Custom, CustomArgumentHandling, ImplementedAs=assertCondition] void assert(in boolean condition); [CustomArgumentHandling] void count(); [CustomArgumentHandling] void markTimeline(); @@ -51,8 +51,8 @@ module window { [Custom] void profileEnd(in DOMString title); #endif - void time(in [ConvertUndefinedOrNullToNullString,Optional=CallWithDefaultValue] DOMString title); - [CustomArgumentHandling] void timeEnd(in [ConvertUndefinedOrNullToNullString] DOMString title); + void time(in [TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=CallWithDefaultValue] DOMString title); + [CustomArgumentHandling] void timeEnd(in [TreatNullAs=NullString, TreatUndefinedAs=NullString] DOMString title); [CustomArgumentHandling] void timeStamp(); [CustomArgumentHandling] void group(); [CustomArgumentHandling] void groupCollapsed(); diff --git a/Source/WebCore/page/DOMSelection.idl b/Source/WebCore/page/DOMSelection.idl index 8a28e6ddb..ccd30e375 100644 --- a/Source/WebCore/page/DOMSelection.idl +++ b/Source/WebCore/page/DOMSelection.idl @@ -32,7 +32,7 @@ module window { // This is based off of Mozilla's Selection interface // https://developer.mozilla.org/En/DOM/Selection interface [ - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] DOMSelection { readonly attribute Node anchorNode; @@ -67,7 +67,7 @@ module window { void addRange(in [Optional=CallWithDefaultValue] Range range); #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - [DontEnum] DOMString toString(); + [NotEnumerable] DOMString toString(); #endif // WebKit extensions diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp index f6fe47b69..2597f864f 100644 --- a/Source/WebCore/page/DOMWindow.cpp +++ b/Source/WebCore/page/DOMWindow.cpp @@ -874,7 +874,7 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t) // Give the embedder a chance to intercept this postMessage because this // DOMWindow might be a proxy for another in browsers that support // postMessage calls across WebKit instances. - if (isCurrentlyDisplayedInFrame() && m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), PassRefPtr<MessageEvent>(event).leakRef())) + if (isCurrentlyDisplayedInFrame() && m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get())) return; if (timer->targetOrigin()) { @@ -1550,8 +1550,11 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event if (!EventTarget::addEventListener(eventType, listener, useCapture)) return false; - if (Document* document = this->document()) + if (Document* document = this->document()) { document->addListenerTypeIfNeeded(eventType); + if (eventType == eventNames().mousewheelEvent) + document->didAddWheelEventHandler(); + } if (eventType == eventNames().unloadEvent) addUnloadEventListener(this); @@ -1572,6 +1575,11 @@ bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener if (!EventTarget::removeEventListener(eventType, listener, useCapture)) return false; + if (Document* document = this->document()) { + if (eventType == eventNames().mousewheelEvent) + document->didRemoveWheelEventHandler(); + } + if (eventType == eventNames().unloadEvent) removeUnloadEventListener(this); else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this)) @@ -1889,15 +1897,6 @@ void DOMWindow::showModalDialog(const String& urlString, const String& dialogFea dialogFrame->page()->chrome()->runModal(); } -#if ENABLE(BLOB) -DOMURL* DOMWindow::webkitURL() const -{ - if (!m_domURL && isCurrentlyDisplayedInFrame()) - m_domURL = DOMURL::create(this->scriptExecutionContext()); - return m_domURL.get(); -} -#endif - #if ENABLE(QUOTA) StorageInfo* DOMWindow::webkitStorageInfo() const { diff --git a/Source/WebCore/page/DOMWindow.h b/Source/WebCore/page/DOMWindow.h index 38e8c5d73..96a58e583 100644 --- a/Source/WebCore/page/DOMWindow.h +++ b/Source/WebCore/page/DOMWindow.h @@ -351,10 +351,6 @@ namespace WebCore { using RefCounted<DOMWindow>::ref; using RefCounted<DOMWindow>::deref; -#if ENABLE(BLOB) - DOMURL* webkitURL() const; -#endif - #if ENABLE(DEVICE_ORIENTATION) DEFINE_ATTRIBUTE_EVENT_LISTENER(devicemotion); DEFINE_ATTRIBUTE_EVENT_LISTENER(deviceorientation); diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl index 6eb74773d..41ace04d0 100644 --- a/Source/WebCore/page/DOMWindow.idl +++ b/Source/WebCore/page/DOMWindow.idl @@ -28,23 +28,22 @@ module window { interface [ CheckDomainSecurity, - CustomDefineGetter, - CustomDefineSetter, + JSCustomDefineOwnProperty, CustomDeleteProperty, CustomGetOwnPropertySlot, CustomGetPropertyNames, - CustomMarkFunction, - CustomNativeConverter, + JSCustomMarkFunction, + JSCustomToNativeObject, CustomPutFunction, EventTarget, ExtendsDOMGlobalObject, - GenerateNativeConverter, + JSGenerateToNativeObject, ReplaceableConstructor, - LegacyParent=JSDOMWindowBase + JSLegacyParent=JSDOMWindowBase ] DOMWindow { // DOM Level 0 attribute [Replaceable] Screen screen; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet, JSCCustomGetter] History history; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter, JSCustomGetter] History history; attribute [Replaceable] BarInfo locationbar; attribute [Replaceable] BarInfo menubar; attribute [Replaceable] BarInfo personalbar; @@ -54,14 +53,14 @@ module window { attribute [Replaceable] Navigator navigator; attribute [Replaceable] Navigator clientInformation; readonly attribute Crypto crypto; - attribute [DoNotCheckDomainSecurity, JSCCustom, V8CustomSetter, V8Unforgeable, CPPCustom] Location location; + attribute [DoNotCheckDomainSecurity, JSCustom, V8CustomSetter, V8Unforgeable, CPPCustom] Location location; attribute [Replaceable, CustomGetter, V8CustomSetter] Event event; DOMSelection getSelection(); - readonly attribute [CheckNodeSecurity] Element frameElement; + readonly attribute [CheckAccessToNode] Element frameElement; [DoNotCheckDomainSecurity] void focus(); [DoNotCheckDomainSecurity] void blur(); @@ -81,7 +80,7 @@ module window { void alert(in [Optional=CallWithDefaultValue] DOMString message); boolean confirm(in [Optional=CallWithDefaultValue] DOMString message); [ConvertNullStringTo=Null] DOMString prompt(in [Optional=CallWithDefaultValue] DOMString message, - in [ConvertUndefinedOrNullToNullString,Optional=CallWithDefaultValue] DOMString defaultValue); + in [TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=CallWithDefaultValue] DOMString defaultValue); boolean find(in [Optional=CallWithDefaultValue] DOMString string, in [Optional=CallWithDefaultValue] boolean caseSensitive, @@ -116,7 +115,7 @@ module window { readonly attribute [DoNotCheckDomainSecurity] boolean closed; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet] unsigned long length; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter] unsigned long length; attribute DOMString name; @@ -128,13 +127,13 @@ module window { #endif // Self referential attributes - attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow self; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter] DOMWindow self; readonly attribute [DoNotCheckDomainSecurity, V8Unforgeable] DOMWindow window; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow frames; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter] DOMWindow frames; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet, V8CustomSetter] DOMWindow opener; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow parent; - attribute [Replaceable, DoNotCheckDomainSecurityOnGet, V8Unforgeable, V8ReadOnly] DOMWindow top; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter, V8CustomSetter] DOMWindow opener; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter] DOMWindow parent; + attribute [Replaceable, DoNotCheckDomainSecurityOnGetter, V8Unforgeable, V8ReadOnly] DOMWindow top; // DOM Level 2 AbstractView Interface readonly attribute Document document; @@ -147,7 +146,7 @@ module window { // DOM Level 2 Style Interface CSSStyleDeclaration getComputedStyle(in [Optional=CallWithDefaultValue] Element element, - in [ConvertUndefinedOrNullToNullString,Optional=CallWithDefaultValue] DOMString pseudoElement); + in [TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=CallWithDefaultValue] DOMString pseudoElement); // WebKit extensions #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT @@ -162,21 +161,21 @@ module window { WebKitPoint webkitConvertPointFromNodeToPage(in [Optional=CallWithDefaultValue] Node node, in [Optional=CallWithDefaultValue] WebKitPoint p); - readonly attribute [EnabledAtRuntime] DOMApplicationCache applicationCache; + readonly attribute [V8EnabledAtRuntime] DOMApplicationCache applicationCache; - readonly attribute [EnabledAtRuntime] Storage sessionStorage + readonly attribute [V8EnabledAtRuntime] Storage sessionStorage getter raises(DOMException); - readonly attribute [EnabledAtRuntime] Storage localStorage + readonly attribute [V8EnabledAtRuntime] Storage localStorage getter raises(DOMException); #if defined(ENABLE_NOTIFICATIONS) && ENABLE_NOTIFICATIONS - readonly attribute [EnabledAtRuntime] NotificationCenter webkitNotifications; + readonly attribute [V8EnabledAtRuntime] NotificationCenter webkitNotifications; #endif #if defined(ENABLE_FILE_SYSTEM) && ENABLE_FILE_SYSTEM const unsigned short TEMPORARY = 0; const unsigned short PERSISTENT = 1; - [EnabledAtRuntime=FileSystem] void webkitRequestFileSystem(in unsigned short type, in long long size, in [Callback] FileSystemCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); - [EnabledAtRuntime=FileSystem] void webkitResolveLocalFileSystemURL(in DOMString url, in [Callback, Optional] EntryCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); + [V8EnabledAtRuntime=FileSystem] void webkitRequestFileSystem(in unsigned short type, in long long size, in [Callback] FileSystemCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); + [V8EnabledAtRuntime=FileSystem] void webkitResolveLocalFileSystemURL(in DOMString url, in [Callback, Optional] EntryCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); #endif #if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS @@ -228,9 +227,9 @@ module window { #endif // Base64 - DOMString atob(in [TreatNullAs=EmptyString,Optional=CallWithDefaultValue] DOMString string) + DOMString atob(in [TreatNullAs=NullString,Optional=CallWithDefaultValue] DOMString string) raises(DOMException); - DOMString btoa(in [TreatNullAs=EmptyString,Optional=CallWithDefaultValue] DOMString string) + DOMString btoa(in [TreatNullAs=NullString,Optional=CallWithDefaultValue] DOMString string) raises(DOMException); // Events @@ -314,15 +313,15 @@ module window { #if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS attribute EventListener onorientationchange; #endif - attribute [Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchstart; - attribute [Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchmove; - attribute [Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchend; - attribute [Conditional=TOUCH_EVENTS,EnabledAtRuntime] EventListener ontouchcancel; + attribute [Conditional=TOUCH_EVENTS,V8EnabledAtRuntime] EventListener ontouchstart; + attribute [Conditional=TOUCH_EVENTS,V8EnabledAtRuntime] EventListener ontouchmove; + attribute [Conditional=TOUCH_EVENTS,V8EnabledAtRuntime] EventListener ontouchend; + attribute [Conditional=TOUCH_EVENTS,V8EnabledAtRuntime] EventListener ontouchcancel; - attribute [Conditional=DEVICE_ORIENTATION,EnabledAtRuntime] EventListener ondevicemotion; - attribute [Conditional=DEVICE_ORIENTATION,EnabledAtRuntime] EventListener ondeviceorientation; + attribute [Conditional=DEVICE_ORIENTATION,V8EnabledAtRuntime] EventListener ondevicemotion; + attribute [Conditional=DEVICE_ORIENTATION,V8EnabledAtRuntime] EventListener ondeviceorientation; - attribute [Conditional=MEDIA_STREAM,EnabledAtRuntime] PeerConnectionConstructor webkitPeerConnection; + attribute [Conditional=MEDIA_STREAM,V8EnabledAtRuntime] PeerConnectionConstructor webkitPeerConnection; // EventTarget interface [Custom] void addEventListener(in DOMString type, @@ -398,7 +397,7 @@ module window { attribute EntityConstructor Entity; attribute EntityReferenceConstructor EntityReference; attribute ProcessingInstructionConstructor ProcessingInstruction; - attribute [Conditional=SHADOW_DOM, EnabledAtRuntime=shadowDOM] ShadowRootConstructor WebKitShadowRoot; + attribute [Conditional=SHADOW_DOM, V8EnabledAtRuntime=shadowDOM] ShadowRootConstructor WebKitShadowRoot; attribute HTMLDocumentConstructor HTMLDocument; @@ -472,8 +471,8 @@ module window { attribute [Conditional=MICRODATA] HTMLPropertiesCollectionConstructor HTMLPropertiesCollection; attribute HTMLUnknownElementConstructor HTMLUnknownElement; - attribute [JSCCustomGetter, CustomConstructor] HTMLImageElementConstructorConstructor Image; // Usable with new operator - attribute [JSCCustomGetter] HTMLOptionElementConstructorConstructor Option; // Usable with new operator + attribute [JSCustomGetter, CustomConstructor] HTMLImageElementConstructorConstructor Image; // Usable with new operator + attribute [JSCustomGetter] HTMLOptionElementConstructorConstructor Option; // Usable with new operator attribute CanvasPatternConstructor CanvasPattern; attribute CanvasGradientConstructor CanvasGradient; @@ -526,8 +525,8 @@ module window { attribute WheelEventConstructor WheelEvent; attribute XMLHttpRequestProgressEventConstructor XMLHttpRequestProgressEvent; attribute [Conditional=SVG] SVGZoomEventConstructor SVGZoomEvent; - attribute [Conditional=DEVICE_ORIENTATION, EnabledAtRuntime] DeviceMotionEventConstructor DeviceMotionEvent; - attribute [Conditional=DEVICE_ORIENTATION, EnabledAtRuntime] DeviceOrientationEventConstructor DeviceOrientationEvent; + attribute [Conditional=DEVICE_ORIENTATION, V8EnabledAtRuntime] DeviceMotionEventConstructor DeviceMotionEvent; + attribute [Conditional=DEVICE_ORIENTATION, V8EnabledAtRuntime] DeviceOrientationEventConstructor DeviceOrientationEvent; attribute [Conditional=TOUCH_EVENTS] TouchEventConstructor TouchEvent; attribute StorageEventConstructor StorageEvent; attribute [Conditional=INPUT_SPEECH] SpeechInputEventConstructor SpeechInputEvent; @@ -579,16 +578,16 @@ module window { #endif #if defined(ENABLE_SHARED_WORKERS) && ENABLE_SHARED_WORKERS - attribute [JSCCustomGetter, EnabledAtRuntime] SharedWorkerConstructor SharedWorker; // Usable with the new operator + attribute [JSCustomGetter, V8EnabledAtRuntime] SharedWorkerConstructor SharedWorker; // Usable with the new operator #endif #if defined(ENABLE_VIDEO_TRACK) && ENABLE_VIDEO_TRACK - attribute [EnabledAtRuntime=webkitVideoTrack] HTMLTrackElementConstructor HTMLTrackElement; - attribute [EnabledAtRuntime=webkitVideoTrack] TextTrackConstructor TextTrack; - attribute [EnabledAtRuntime=webkitVideoTrack] TextTrackCueConstructor TextTrackCue; // Usable with the new operator - attribute [EnabledAtRuntime=webkitVideoTrack] TextTrackCueListConstructor TextTrackCueList; - attribute [EnabledAtRuntime=webkitVideoTrack] TextTrackListConstructor TextTrackList; - attribute [EnabledAtRuntime=webkitVideoTrack] TrackEventConstructor TrackEvent; + attribute [V8EnabledAtRuntime=webkitVideoTrack] HTMLTrackElementConstructor HTMLTrackElement; + attribute [V8EnabledAtRuntime=webkitVideoTrack] TextTrackConstructor TextTrack; + attribute [V8EnabledAtRuntime=webkitVideoTrack] TextTrackCueConstructor TextTrackCue; // Usable with the new operator + attribute [V8EnabledAtRuntime=webkitVideoTrack] TextTrackCueListConstructor TextTrackCueList; + attribute [V8EnabledAtRuntime=webkitVideoTrack] TextTrackListConstructor TextTrackList; + attribute [V8EnabledAtRuntime=webkitVideoTrack] TrackEventConstructor TrackEvent; #endif attribute DOMPluginConstructor Plugin; @@ -602,14 +601,14 @@ module window { attribute StorageConstructor Storage; - attribute [JSCCustomGetter, Conditional=VIDEO, EnabledAtRuntime] HTMLAudioElementConstructorConstructor Audio; // Usable with the new operator - attribute [Conditional=VIDEO, EnabledAtRuntime] HTMLAudioElementConstructor HTMLAudioElement; - attribute [Conditional=VIDEO, EnabledAtRuntime] HTMLMediaElementConstructor HTMLMediaElement; - attribute [Conditional=VIDEO, EnabledAtRuntime] HTMLVideoElementConstructor HTMLVideoElement; - attribute [Conditional=VIDEO, EnabledAtRuntime] MediaErrorConstructor MediaError; - attribute [Conditional=VIDEO, EnabledAtRuntime] TimeRangesConstructor TimeRanges; - attribute [Conditional=VIDEO, EnabledAtRuntime] HTMLSourceElementConstructor HTMLSourceElement; - attribute [Conditional=VIDEO, EnabledAtRuntime] MediaControllerConstructor MediaController; + attribute [JSCustomGetter, Conditional=VIDEO, V8EnabledAtRuntime] HTMLAudioElementConstructorConstructor Audio; // Usable with the new operator + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLAudioElementConstructor HTMLAudioElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLMediaElementConstructor HTMLMediaElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLVideoElementConstructor HTMLVideoElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] MediaErrorConstructor MediaError; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] TimeRangesConstructor TimeRanges; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] HTMLSourceElementConstructor HTMLSourceElement; + attribute [Conditional=VIDEO, V8EnabledAtRuntime] MediaControllerConstructor MediaController; #if defined(ENABLE_ANIMATION_API) && ENABLE_ANIMATION_API attribute WebKitAnimationConstructor WebKitAnimation; @@ -783,10 +782,10 @@ module window { attribute [Conditional=BLOB] WebKitBlobBuilderConstructor WebKitBlobBuilder; - readonly attribute [Conditional=BLOB] DOMURL webkitURL; + attribute [Conditional=BLOB] DOMURLConstructor webkitURL; #if defined(ENABLE_QUOTA) && ENABLE_QUOTA - readonly attribute [EnabledAtRuntime=Quota] StorageInfo webkitStorageInfo; + readonly attribute [V8EnabledAtRuntime=Quota] StorageInfo webkitStorageInfo; #endif attribute [Conditional=MUTATION_OBSERVERS] WebKitMutationObserverConstructor WebKitMutationObserver; @@ -795,7 +794,7 @@ module window { #if defined(V8_BINDING) && V8_BINDING // window.toString() requires special handling in V8 - [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, DontEnum] DOMString toString(); + [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, NotEnumerable] DOMString toString(); #endif // defined(V8_BINDING) }; diff --git a/Source/WebCore/page/DragController.cpp b/Source/WebCore/page/DragController.cpp index a47b6a4bc..7919d761e 100644 --- a/Source/WebCore/page/DragController.cpp +++ b/Source/WebCore/page/DragController.cpp @@ -27,7 +27,6 @@ #include "DragController.h" #if ENABLE(DRAG_SUPPORT) -#include "CSSMutableStyleDeclaration.h" #include "Clipboard.h" #include "ClipboardAccessPolicy.h" #include "CachedResourceLoader.h" @@ -64,6 +63,7 @@ #include "ResourceRequest.h" #include "SecurityOrigin.h" #include "Settings.h" +#include "StylePropertySet.h" #include "Text.h" #include "TextEvent.h" #include "htmlediting.h" @@ -447,12 +447,12 @@ bool DragController::concludeEditDrag(DragData* dragData) if (!color.isValid()) return false; RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange(); - RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); + RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyColor, color.serialized(), false); - if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get())) + if (!innerFrame->editor()->shouldApplyStyle(style->ensureCSSStyleDeclaration(), innerRange.get())) return false; m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); - innerFrame->editor()->applyStyle(style.get(), EditActionSetColor); + innerFrame->editor()->applyStyle(style->ensureCSSStyleDeclaration(), EditActionSetColor); return true; } diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index a2f322e26..9acfc54d2 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -60,6 +60,7 @@ #include "MouseEvent.h" #include "MouseEventWithHitTestResults.h" #include "Page.h" +#include "PlatformEvent.h" #include "PlatformKeyboardEvent.h" #include "PlatformWheelEvent.h" #include "PluginDocument.h" @@ -142,6 +143,73 @@ private: Cursor m_cursor; }; +#if ENABLE(TOUCH_EVENTS) +class SyntheticTouchPoint : public PlatformTouchPoint { +public: + + // The default values are based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html + explicit SyntheticTouchPoint(const PlatformMouseEvent& event) + { + const static int idDefaultValue = 0; + const static int radiusYDefaultValue = 1; + const static int radiusXDefaultValue = 1; + const static float rotationAngleDefaultValue = 0.0f; + const static float forceDefaultValue = 1.0f; + + m_id = idDefaultValue; // There is only one active TouchPoint. + m_screenPos = event.globalPosition(); + m_pos = event.position(); + m_radiusY = radiusYDefaultValue; + m_radiusX = radiusXDefaultValue; + m_rotationAngle = rotationAngleDefaultValue; + m_force = forceDefaultValue; + + PlatformEvent::Type type = event.type(); + ASSERT(type == PlatformEvent::MouseMoved || type == PlatformEvent::MousePressed || type == PlatformEvent::MouseReleased); + + switch (type) { + case PlatformEvent::MouseMoved: + m_state = TouchMoved; + break; + case PlatformEvent::MousePressed: + m_state = TouchPressed; + break; + case PlatformEvent::MouseReleased: + m_state = TouchReleased; + break; + default: + ASSERT_NOT_REACHED(); + break; + } + } +}; + +class SyntheticSingleTouchEvent : public PlatformTouchEvent { +public: + explicit SyntheticSingleTouchEvent(const PlatformMouseEvent& event) + { + switch (event.type()) { + case PlatformEvent::MouseMoved: + m_type = TouchMove; + break; + case PlatformEvent::MousePressed: + m_type = TouchStart; + break; + case PlatformEvent::MouseReleased: + m_type = TouchEnd; + break; + default: + ASSERT_NOT_REACHED(); + m_type = NoType; + break; + } + m_timestamp = event.timestamp(); + m_modifiers = event.modifiers(); + m_touchPoints.append(SyntheticTouchPoint(event)); + } +}; +#endif + static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode) { if (!delta) @@ -1375,6 +1443,12 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) { RefPtr<FrameView> protector(m_frame->view()); +#if ENABLE(TOUCH_EVENTS) + bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent); + if (defaultPrevented) + return true; +#endif + UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); // FIXME (bug 68185): this call should be made at another abstraction layer @@ -1401,7 +1475,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) HitTestRequest request(HitTestRequest::Active); // Save the document point we generate in case the window coordinate is invalidated by what happens // when we dispatch the event. - IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.position()); + LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.position()); MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); if (!targetNode(mev)) { @@ -1561,6 +1635,13 @@ bool EventHandler::mouseMoved(const PlatformMouseEvent& event) { RefPtr<FrameView> protector(m_frame->view()); +#if ENABLE(TOUCH_EVENTS) + // FIXME: this should be moved elsewhere to also be able to dispatch touchcancel events. + bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(event); + if (defaultPrevented) + return true; +#endif + HitTestResult hoveredNode = HitTestResult(LayoutPoint()); bool result = handleMouseMoveEvent(event, &hoveredNode); @@ -1569,8 +1650,10 @@ bool EventHandler::mouseMoved(const PlatformMouseEvent& event) return result; if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) { - if (page->containsScrollableArea(layer)) - layer->mouseMovedInContentArea(); + if (FrameView* frameView = m_frame->view()) { + if (frameView->containsScrollableArea(layer)) + layer->mouseMovedInContentArea(); + } } if (FrameView* frameView = m_frame->view()) @@ -1698,7 +1781,13 @@ void EventHandler::invalidateClick() bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) { RefPtr<FrameView> protector(m_frame->view()); - + +#if ENABLE(TOUCH_EVENTS) + bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent); + if (defaultPrevented) + return true; +#endif + UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); #if ENABLE(PAN_SCROLLING) @@ -2030,10 +2119,14 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo } } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) { // The mouse has moved between layers. - if (page->containsScrollableArea(layerForLastNode)) - layerForLastNode->mouseExitedContentArea(); + if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) { + if (FrameView* frameView = frame->view()) { + if (frameView->containsScrollableArea(layerForLastNode)) + layerForLastNode->mouseExitedContentArea(); + } + } } - + if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) { // The mouse has moved between frames. if (Frame* frame = m_nodeUnderMouse->document()->frame()) { @@ -2042,10 +2135,14 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo } } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) { // The mouse has moved between layers. - if (page->containsScrollableArea(layerForNodeUnderMouse)) - layerForNodeUnderMouse->mouseEnteredContentArea(); + if (Frame* frame = m_nodeUnderMouse->document()->frame()) { + if (FrameView* frameView = frame->view()) { + if (frameView->containsScrollableArea(layerForNodeUnderMouse)) + layerForNodeUnderMouse->mouseEnteredContentArea(); + } + } } - + if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) { m_lastNodeUnderMouse = 0; m_lastScrollbarUnderMouse = 0; @@ -3194,6 +3291,8 @@ static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State return eventNames().touchstartEvent; case PlatformTouchPoint::TouchMoved: return eventNames().touchmoveEvent; + case PlatformTouchPoint::TouchStationary: + // TouchStationary state is not converted to touch events, so fall through to assert. default: ASSERT_NOT_REACHED(); return emptyAtom; @@ -3249,6 +3348,9 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) case PlatformTouchPoint::TouchCancelled: hitType |= HitTestRequest::Release; break; + case PlatformTouchPoint::TouchStationary: + hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; + break; default: ASSERT_NOT_REACHED(); break; @@ -3281,7 +3383,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) // we also remove it from the map. touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); } else - // No hittest is performed on move, since the target is not allowed to change anyway. + // No hittest is performed on move or stationary, since the target is not allowed to change anyway. touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey); if (!touchTarget.get()) @@ -3362,7 +3464,21 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) return defaultPrevented; } +bool EventHandler::dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent& event) +{ + if (!m_frame || !m_frame->settings() || !m_frame->settings()->isTouchEventEmulationEnabled()) + return false; + + PlatformEvent::Type eventType = event.type(); + if (eventType != PlatformEvent::MouseMoved && eventType != PlatformEvent::MousePressed && eventType != PlatformEvent::MouseReleased) + return false; + if (eventType == PlatformEvent::MouseMoved && !m_touchPressed) + return false; + + SyntheticSingleTouchEvent touchEvent(event); + return handleTouchEvent(touchEvent); +} #endif diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h index 547bfe57d..7733a0f65 100644 --- a/Source/WebCore/page/EventHandler.h +++ b/Source/WebCore/page/EventHandler.h @@ -264,6 +264,10 @@ private: void fakeMouseMoveEventTimerFired(Timer<EventHandler>*); void cancelFakeMouseMoveEvent(); +#if ENABLE(TOUCH_EVENTS) + bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&); +#endif + void invalidateClick(); Node* nodeUnderMouse() const; diff --git a/Source/WebCore/page/EventSource.idl b/Source/WebCore/page/EventSource.idl index 4c4433f7a..9b7fe38dc 100644 --- a/Source/WebCore/page/EventSource.idl +++ b/Source/WebCore/page/EventSource.idl @@ -38,7 +38,7 @@ module window { CallWith=ScriptExecutionContext, ConstructorRaisesException, EventTarget, - NoStaticTables + JSNoStaticTables ] EventSource { readonly attribute DOMString URL; // Lowercased .url is the one in the spec, but leaving .URL for compatibility reasons. diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp index b0ef2110f..51426a308 100644 --- a/Source/WebCore/page/FocusController.cpp +++ b/Source/WebCore/page/FocusController.cpp @@ -88,6 +88,7 @@ FocusController::FocusController(Page* page) , m_isActive(false) , m_isFocused(false) , m_isChangingFocusedFrame(false) + , m_containingWindowIsVisible(false) { } @@ -573,16 +574,6 @@ void FocusController::setActive(bool active) view->updateLayoutAndStyleIfNeededRecursive(); view->updateControlTints(); } - - if (const HashSet<ScrollableArea*>* scrollableAreas = m_page->scrollableAreaSet()) { - HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); - for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) { - if (!active) - (*it)->contentAreaDidHide(); - else - (*it)->contentAreaDidShow(); - } - } } focusedOrMainFrame()->selection()->pageActivationChanged(); @@ -591,6 +582,45 @@ void FocusController::setActive(bool active) dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), active); } +static void contentAreaDidShowOrHide(ScrollableArea* scrollableArea, bool didShow) +{ + if (didShow) + scrollableArea->contentAreaDidShow(); + else + scrollableArea->contentAreaDidHide(); +} + +void FocusController::setContainingWindowIsVisible(bool containingWindowIsVisible) +{ + if (m_containingWindowIsVisible == containingWindowIsVisible) + return; + + m_containingWindowIsVisible = containingWindowIsVisible; + + FrameView* view = m_page->mainFrame()->view(); + if (!view) + return; + + contentAreaDidShowOrHide(view, containingWindowIsVisible); + + for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + FrameView* frameView = frame->view(); + if (!frameView) + continue; + + const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas(); + if (!scrollableAreas) + continue; + + for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { + ScrollableArea* scrollableArea = *it; + ASSERT(scrollableArea->isOnActivePage()); + + contentAreaDidShowOrHide(scrollableArea, containingWindowIsVisible); + } + } +} + static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest) { ASSERT(candidate.visibleNode->isElementNode()); diff --git a/Source/WebCore/page/FocusController.h b/Source/WebCore/page/FocusController.h index 6880a1c45..3b56377bd 100644 --- a/Source/WebCore/page/FocusController.h +++ b/Source/WebCore/page/FocusController.h @@ -63,6 +63,9 @@ public: void setFocused(bool); bool isFocused() const { return m_isFocused; } + void setContainingWindowIsVisible(bool); + bool containingWindowIsVisible() const { return m_containingWindowIsVisible; } + bool transferFocusToElementInShadowRoot(Element* shadowHost, bool restorePreviousSelection); private: @@ -96,6 +99,7 @@ private: bool m_isActive; bool m_isFocused; bool m_isChangingFocusedFrame; + bool m_containingWindowIsVisible; }; diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp index e1f5bcf99..72ddd62cb 100644 --- a/Source/WebCore/page/Frame.cpp +++ b/Source/WebCore/page/Frame.cpp @@ -33,7 +33,6 @@ #include "ApplyStyleCommand.h" #include "BackForwardController.h" #include "CSSComputedStyleDeclaration.h" -#include "CSSMutableStyleDeclaration.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" @@ -80,6 +79,7 @@ #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "Settings.h" +#include "StylePropertySet.h" #include "TextIterator.h" #include "TextResourceDecoder.h" #include "UserContentURLPattern.h" @@ -290,11 +290,11 @@ void Frame::setDocument(PassRefPtr<Document> newDoc) // Update the cached 'document' property, which is now stale. m_script.updateDocument(); - if (m_page) { - m_page->updateViewportArguments(); - if (m_page->mainFrame() == this) - notifyChromeClientWheelEventHandlerCountChanged(); - } + if (m_doc) + m_doc->updateViewportArguments(); + + if (m_page && m_page->mainFrame() == this) + notifyChromeClientWheelEventHandlerCountChanged(); } #if ENABLE(ORIENTATION_EVENTS) @@ -668,6 +668,9 @@ void Frame::pageDestroyed() if (m_domWindow) { m_domWindow->resetGeolocation(); +#if ENABLE(NOTIFICATIONS) + m_domWindow->resetNotifications(); +#endif m_domWindow->pageDestroyed(); } @@ -1068,7 +1071,7 @@ DragImageRef Frame::nodeImage(Node* node) m_doc->updateLayout(); m_view->setNodeToDraw(node); // Enable special sub-tree drawing mode. - IntRect topLevelRect; + LayoutRect topLevelRect; IntRect paintingRect = renderer->paintingRootRect(topLevelRect); OwnPtr<ImageBuffer> buffer(ImageBuffer::create(paintingRect.size())); diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index 9fc1cc605..baba068e4 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -152,16 +152,17 @@ FrameView::FrameView(Frame* frame) { init(); - if (m_frame) { - if (Page* page = m_frame->page()) { - m_page = page; - m_page->addScrollableArea(this); + // FIXME: Can m_frame ever be null here? + if (!m_frame) + return; - if (m_frame == m_page->mainFrame()) { - ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); - ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); - } - } + Page* page = m_frame->page(); + if (!page) + return; + + if (m_frame == page->mainFrame()) { + ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); + ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); } } @@ -202,9 +203,6 @@ FrameView::~FrameView() ASSERT(!m_scrollCorner); ASSERT(m_actionScheduler->isEmpty()); - if (m_page) - m_page->removeScrollableArea(this); - if (m_frame) { ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); RenderPart* renderer = m_frame->ownerRenderer(); @@ -323,21 +321,6 @@ void FrameView::detachCustomScrollbars() } } -void FrameView::didAddHorizontalScrollbar(Scrollbar* scrollbar) -{ - if (m_frame && m_frame->document()) - m_frame->document()->didAddWheelEventHandler(); - ScrollView::didAddHorizontalScrollbar(scrollbar); -} - -void FrameView::willRemoveHorizontalScrollbar(Scrollbar* scrollbar) -{ - ScrollView::willRemoveHorizontalScrollbar(scrollbar); - // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback? - if (m_frame && m_frame->document()) - m_frame->document()->didRemoveWheelEventHandler(); -} - void FrameView::recalculateScrollbarOverlayStyle() { ScrollbarOverlayStyle oldOverlayStyle = scrollbarOverlayStyle(); @@ -1242,8 +1225,8 @@ void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object) void FrameView::zoomAnimatorTransformChanged(float scale, float x, float y, ZoomAnimationState state) { if (state == ZoomAnimationFinishing) { - m_page->setPageScaleFactor(m_page->pageScaleFactor() * scale, - IntPoint(scale * scrollX() - x, scale * scrollY() - y)); + if (Page* page = m_frame->page()) + page->setPageScaleFactor(page->pageScaleFactor() * scale, IntPoint(scale * scrollX() - x, scale * scrollY() - y)); scrollAnimator()->resetZoom(); } @@ -2280,8 +2263,10 @@ void FrameView::performPostLayoutTasks() if (m_firstLayoutCallbackPending) { m_firstLayoutCallbackPending = false; m_frame->loader()->didFirstLayout(); - if (Page* page = m_frame->page()) - page->startCountingRelevantRepaintedObjects(); + if (Page* page = m_frame->page()) { + if (page->mainFrame() == m_frame) + page->startCountingRelevantRepaintedObjects(); + } } // Ensure that we always send this eventually. @@ -2305,6 +2290,13 @@ void FrameView::performPostLayoutTasks() break; } +#if ENABLE(THREADED_SCROLLING) + if (Page* page = m_frame->page()) { + if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) + scrollingCoordinator->frameViewLayoutUpdated(this); + } +#endif + scrollToAnchor(); m_actionScheduler->resume(); @@ -2542,6 +2534,12 @@ ScrollableArea* FrameView::enclosingScrollableArea() const return 0; } +IntRect FrameView::scrollableAreaBoundingBox() const +{ + // FIXME: This isn't correct for transformed frames. We probably need to ask the renderer instead. + return frameRect(); +} + bool FrameView::shouldSuspendScrollAnimations() const { return m_frame->loader()->state() != FrameStateComplete; @@ -2566,18 +2564,16 @@ void FrameView::setAnimatorsAreActive() if (!page) return; - const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet(); - if (!scrollableAreas) + scrollAnimator()->setIsActive(); + + if (!m_scrollableAreas) return; - HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); - for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) { - // FIXME: This extra check to make sure the ScrollableArea is on an active page needs - // to be here as long as the ScrollableArea HashSet lives on Page. But it should really be - // moved to the top-level Document or a similar class that really represents a single - // web page. https://bugs.webkit.org/show_bug.cgi?id=62762 - if ((*it)->isOnActivePage()) - (*it)->scrollAnimator()->setIsActive(); + for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { + ScrollableArea* scrollableArea = *it; + + ASSERT(scrollableArea->isOnActivePage()); + scrollableArea->scrollAnimator()->setIsActive(); } } @@ -2587,21 +2583,28 @@ void FrameView::notifyPageThatContentAreaWillPaint() const if (!page) return; - const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet(); - if (!scrollableAreas) + contentAreaWillPaint(); + + if (!m_scrollableAreas) return; - HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); - for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) - (*it)->contentAreaWillPaint(); + for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { + ScrollableArea* scrollableArea = *it; + + if (!scrollableArea->isOnActivePage()) + continue; + + scrollableArea->contentAreaWillPaint(); + } } bool FrameView::scrollAnimatorEnabled() const { #if ENABLE(SMOOTH_SCROLLING) - if (m_page && m_page->settings()) - return m_page->settings()->scrollAnimatorEnabled(); + if (Page* page = m_frame->page()) + return page->settings()->scrollAnimatorEnabled(); #endif + return false; } @@ -3253,6 +3256,43 @@ void FrameView::setTracksRepaints(bool trackRepaints) m_isTrackingRepaints = trackRepaints; } +void FrameView::addScrollableArea(ScrollableArea* scrollableArea) +{ + if (!m_scrollableAreas) + m_scrollableAreas = adoptPtr(new ScrollableAreaSet); + m_scrollableAreas->add(scrollableArea); +} + +void FrameView::removeScrollableArea(ScrollableArea* scrollableArea) +{ + if (!m_scrollableAreas) + return; + m_scrollableAreas->remove(scrollableArea); +} + +bool FrameView::containsScrollableArea(ScrollableArea* scrollableArea) const +{ + if (!m_scrollableAreas) + return false; + return m_scrollableAreas->contains(scrollableArea); +} + +void FrameView::addChild(PassRefPtr<Widget> widget) +{ + if (widget->isFrameView()) + addScrollableArea(static_cast<FrameView*>(widget.get())); + + ScrollView::addChild(widget); +} + +void FrameView::removeChild(Widget* widget) +{ + if (widget->isFrameView()) + removeScrollableArea(static_cast<FrameView*>(widget)); + + ScrollView::removeChild(widget); +} + bool FrameView::isVerticalDocument() const { RenderView* root = rootRenderer(this); diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h index 466a88939..51fe7c370 100644 --- a/Source/WebCore/page/FrameView.h +++ b/Source/WebCore/page/FrameView.h @@ -86,8 +86,6 @@ public: virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation); virtual bool avoidScrollbarCreation() const; - virtual void didAddHorizontalScrollbar(Scrollbar*); - virtual void willRemoveHorizontalScrollbar(Scrollbar*); virtual void setContentsSize(const IntSize&); @@ -308,6 +306,15 @@ public: void resetTrackedRepaints() { m_trackedRepaintRects.clear(); } const Vector<IntRect>& trackedRepaintRects() const { return m_trackedRepaintRects; } + typedef HashSet<ScrollableArea*> ScrollableAreaSet; + void addScrollableArea(ScrollableArea*); + void removeScrollableArea(ScrollableArea*); + bool containsScrollableArea(ScrollableArea*) const; + const ScrollableAreaSet* scrollableAreas() const { return m_scrollableAreas.get(); } + + virtual void addChild(PassRefPtr<Widget>) OVERRIDE; + virtual void removeChild(Widget*) OVERRIDE; + protected: virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); virtual void scrollContentsSlowPath(const IntRect& updateRect); @@ -362,6 +369,7 @@ private: virtual void setVisibleScrollerThumbRect(const IntRect&); virtual bool isOnActivePage() const; virtual ScrollableArea* enclosingScrollableArea() const; + virtual IntRect scrollableAreaBoundingBox() const OVERRIDE; #if USE(ACCELERATED_COMPOSITING) virtual GraphicsLayer* layerForHorizontalScrollbar() const OVERRIDE; @@ -373,7 +381,6 @@ private: #endif virtual void notifyPageThatContentAreaWillPaint() const; - virtual void disconnectFromPage() { m_page = 0; } virtual bool scrollAnimatorEnabled() const; @@ -476,8 +483,6 @@ private: // Renderer to hold our custom scroll corner. RenderScrollbarPart* m_scrollCorner; - Page* m_page; - // If true, automatically resize the frame view around its content. bool m_shouldAutoSize; bool m_inAutoSize; @@ -486,6 +491,8 @@ private: // The upper bound on the size when autosizing. IntSize m_maxAutoSize; + OwnPtr<ScrollableAreaSet> m_scrollableAreas; + static double s_deferredRepaintDelay; static double s_initialDeferredRepaintDelayDuringLoading; static double s_maxDeferredRepaintDelayDuringLoading; diff --git a/Source/WebCore/page/Geolocation.idl b/Source/WebCore/page/Geolocation.idl index d1d534992..4f159bcb1 100644 --- a/Source/WebCore/page/Geolocation.idl +++ b/Source/WebCore/page/Geolocation.idl @@ -28,7 +28,7 @@ module core { // http://www.w3.org/TR/geolocation-API/#geolocation_interface interface [ Conditional=GEOLOCATION, - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] Geolocation { [Custom] void getCurrentPosition(in PositionCallback successCallback, diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp index 1f5a39f28..a1f9a05f6 100644 --- a/Source/WebCore/page/History.cpp +++ b/Source/WebCore/page/History.cpp @@ -42,6 +42,7 @@ namespace WebCore { History::History(Frame* frame) : DOMWindowProperty(frame) + , m_lastStateObjectRequested(0) { } @@ -54,6 +55,28 @@ unsigned History::length() const return m_frame->page()->backForward()->count(); } +SerializedScriptValue* History::state() +{ + m_lastStateObjectRequested = stateInternal(); + return m_lastStateObjectRequested; +} + +SerializedScriptValue* History::stateInternal() const +{ + if (!m_frame) + return 0; + + if (HistoryItem* historyItem = m_frame->loader()->history()->currentItem()) + return historyItem->stateObject(); + + return 0; +} + +bool History::stateChanged() const +{ + return m_lastStateObjectRequested != stateInternal(); +} + void History::back() { go(-1); diff --git a/Source/WebCore/page/History.h b/Source/WebCore/page/History.h index bd50fccd2..bd6f6aa21 100644 --- a/Source/WebCore/page/History.h +++ b/Source/WebCore/page/History.h @@ -44,6 +44,8 @@ public: static PassRefPtr<History> create(Frame* frame) { return adoptRef(new History(frame)); } unsigned length() const; + SerializedScriptValue* state(); + bool stateChanged() const; void back(); void forward(); void go(int distance); @@ -62,6 +64,10 @@ private: explicit History(Frame*); KURL urlForState(const String& url); + + SerializedScriptValue* stateInternal() const; + + SerializedScriptValue* m_lastStateObjectRequested; }; } // namespace WebCore diff --git a/Source/WebCore/page/History.idl b/Source/WebCore/page/History.idl index ff3701ed2..f7036403a 100644 --- a/Source/WebCore/page/History.idl +++ b/Source/WebCore/page/History.idl @@ -29,22 +29,23 @@ module window { #if defined(V8_BINDING) && V8_BINDING CheckDomainSecurity, #endif - DelegatingGetOwnPropertySlot, - DelegatingPutFunction, - GenerateIsReachable=ImplFrame, + JSCustomGetOwnPropertySlotDelegate, + CustomNamedSetter, + JSGenerateIsReachable=ImplFrame, CustomDeleteProperty, CustomGetPropertyNames, OmitConstructor ] History { readonly attribute unsigned long length; + readonly attribute [CachedAttribute, Custom] SerializedScriptValue state; [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void back(); [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void forward(); [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void go(in [Optional=CallWithDefaultValue] long distance); - [Custom, EnabledAtRuntime] void pushState(in any data, in DOMString title, in [Optional] DOMString url) + [Custom, V8EnabledAtRuntime] void pushState(in any data, in DOMString title, in [Optional] DOMString url) raises(DOMException); - [Custom, EnabledAtRuntime] void replaceState(in any data, in DOMString title, in [Optional] DOMString url) + [Custom, V8EnabledAtRuntime] void replaceState(in any data, in DOMString title, in [Optional] DOMString url) raises(DOMException); }; diff --git a/Source/WebCore/page/Location.idl b/Source/WebCore/page/Location.idl index d510052c3..d5d27e2c6 100644 --- a/Source/WebCore/page/Location.idl +++ b/Source/WebCore/page/Location.idl @@ -32,18 +32,18 @@ module window { #if defined(V8_BINDING) && V8_BINDING CheckDomainSecurity, #endif - DelegatingGetOwnPropertySlot, - DelegatingPutFunction, - GenerateIsReachable=ImplFrame, + JSCustomGetOwnPropertySlotDelegate, + CustomNamedSetter, + JSGenerateIsReachable=ImplFrame, CustomDeleteProperty, CustomGetPropertyNames, - CustomDefineGetter, - DelegatingPrototypePutFunction, - CustomPrototypeDefineGetter, + JSCustomDefineOwnProperty, + JSCustomPrototypePutDelegate, + JSCustomPrototypeDefineOwnProperty, OmitConstructor ] Location { #if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP - attribute [DoNotCheckDomainSecurityOnSet, CustomSetter, V8Unforgeable] DOMString href; + attribute [DoNotCheckDomainSecurityOnSetter, CustomSetter, V8Unforgeable] DOMString href; #endif [Custom, V8OnInstance] void assign(in [Optional=CallWithDefaultValue] DOMString url); @@ -64,10 +64,10 @@ module window { #endif #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT - [DontEnum, Custom, V8OnInstance, V8ReadOnly, ImplementationFunction=toStringFunction] DOMString toString(); + [NotEnumerable, Custom, V8OnInstance, V8ReadOnly, ImplementedAs=toStringFunction] DOMString toString(); #endif #if defined(V8_BINDING) && V8_BINDING - [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMObject valueOf(); + [NotEnumerable, Custom, V8OnInstance, V8ReadOnly] DOMObject valueOf(); #endif }; diff --git a/Source/WebCore/page/MemoryInfo.idl b/Source/WebCore/page/MemoryInfo.idl index f04447479..b9149d54d 100644 --- a/Source/WebCore/page/MemoryInfo.idl +++ b/Source/WebCore/page/MemoryInfo.idl @@ -36,7 +36,7 @@ module window { readonly attribute unsigned long totalJSHeapSize; readonly attribute unsigned long usedJSHeapSize; - readonly attribute [JSCCustomGetter] unsigned long jsHeapSizeLimit; + readonly attribute [JSCustomGetter] unsigned long jsHeapSizeLimit; }; diff --git a/Source/WebCore/page/Navigator.idl b/Source/WebCore/page/Navigator.idl index 6fe43e660..213fab125 100644 --- a/Source/WebCore/page/Navigator.idl +++ b/Source/WebCore/page/Navigator.idl @@ -20,7 +20,7 @@ module window { interface [ - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] Navigator { readonly attribute DOMString appCodeName; @@ -41,11 +41,11 @@ module window { readonly attribute boolean onLine; #if defined(ENABLE_GEOLOCATION) && ENABLE_GEOLOCATION - readonly attribute [EnabledAtRuntime] Geolocation geolocation; + readonly attribute [V8EnabledAtRuntime] Geolocation geolocation; #endif #if defined(ENABLE_POINTER_LOCK) && ENABLE_POINTER_LOCK - readonly attribute [EnabledAtRuntime] PointerLock webkitPointer; + readonly attribute [V8EnabledAtRuntime] PointerLock webkitPointer; #endif void getStorageUpdates(); // FIXME: Remove this method or rename to yieldForStorageUpdates. @@ -56,7 +56,7 @@ module window { #endif #if defined(ENABLE_MEDIA_STREAM) && ENABLE_MEDIA_STREAM - [Custom, EnabledAtRuntime] void webkitGetUserMedia(in DOMString options, + [Custom, V8EnabledAtRuntime] void webkitGetUserMedia(in DOMString options, in [Callback=FunctionOnly] NavigatorUserMediaSuccessCallback successCallback, in [Callback=FunctionOnly, Optional] NavigatorUserMediaErrorCallback errorCallback) raises(DOMException); diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp index 2442bf7c2..492e949ee 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp @@ -211,12 +211,6 @@ Page::~Page() for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) frame->pageDestroyed(); - if (m_scrollableAreaSet) { - ScrollableAreaSet::const_iterator end = m_scrollableAreaSet->end(); - for (ScrollableAreaSet::const_iterator it = m_scrollableAreaSet->begin(); it != end; ++it) - (*it)->disconnectFromPage(); - } - m_editorClient->pageDestroyed(); #if ENABLE(INSPECTOR) @@ -240,6 +234,11 @@ Page::~Page() #endif } +ViewportArguments Page::viewportArguments() const +{ + return mainFrame() && mainFrame()->document() ? mainFrame()->document()->viewportArguments() : ViewportArguments(); +} + #if ENABLE(THREADED_SCROLLING) ScrollingCoordinator* Page::scrollingCoordinator() { @@ -430,15 +429,6 @@ void Page::setNeedsRecalcStyleInAllFrames() frame->document()->styleSelectorChanged(DeferRecalcStyle); } -void Page::updateViewportArguments() -{ - if (!mainFrame() || !mainFrame()->document()) - return; - - m_viewportArguments = mainFrame()->document()->viewportArguments(); - chrome()->dispatchViewportPropertiesDidChange(m_viewportArguments); -} - void Page::refreshPlugins(bool reload) { if (!allPages) @@ -1030,27 +1020,6 @@ void Page::privateBrowsingStateChanged() pluginViewBases[i]->privateBrowsingStateChanged(privateBrowsingEnabled); } -void Page::addScrollableArea(ScrollableArea* scrollableArea) -{ - if (!m_scrollableAreaSet) - m_scrollableAreaSet = adoptPtr(new ScrollableAreaSet); - m_scrollableAreaSet->add(scrollableArea); -} - -void Page::removeScrollableArea(ScrollableArea* scrollableArea) -{ - if (!m_scrollableAreaSet) - return; - m_scrollableAreaSet->remove(scrollableArea); -} - -bool Page::containsScrollableArea(ScrollableArea* scrollableArea) const -{ - if (!m_scrollableAreaSet) - return false; - return m_scrollableAreaSet->contains(scrollableArea); -} - #if !ASSERT_DISABLED void Page::checkFrameCountConsistency() const { diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h index 887893f9f..5f6e20649 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h @@ -133,8 +133,7 @@ namespace WebCore { RenderTheme* theme() const { return m_theme.get(); }; - ViewportArguments viewportArguments() const { return m_viewportArguments; } - void updateViewportArguments(); + ViewportArguments viewportArguments() const; static void refreshPlugins(bool reload); PluginData* pluginData() const; @@ -334,12 +333,6 @@ namespace WebCore { void setJavaScriptURLsAreAllowed(bool); bool javaScriptURLsAreAllowed() const; - typedef HashSet<ScrollableArea*> ScrollableAreaSet; - void addScrollableArea(ScrollableArea*); - void removeScrollableArea(ScrollableArea*); - bool containsScrollableArea(ScrollableArea*) const; - const ScrollableAreaSet* scrollableAreaSet() const { return m_scrollableAreaSet.get(); } - // Don't allow more than a certain number of frames in a page. // This seems like a reasonable upper bound, and otherwise mutually // recursive frameset pages can quickly bring the program to its knees @@ -464,12 +457,8 @@ namespace WebCore { ViewMode m_viewMode; - ViewportArguments m_viewportArguments; - double m_minimumTimerInterval; - OwnPtr<ScrollableAreaSet> m_scrollableAreaSet; - bool m_isEditable; #if ENABLE(PAGE_VISIBILITY_API) diff --git a/Source/WebCore/page/PageSerializer.cpp b/Source/WebCore/page/PageSerializer.cpp index 2c3778b46..64d901b7a 100644 --- a/Source/WebCore/page/PageSerializer.cpp +++ b/Source/WebCore/page/PageSerializer.cpp @@ -69,9 +69,9 @@ static bool isCharsetSpecifyingNode(Node* node) if (!element->hasTagName(HTMLNames::metaTag)) return false; HTMLMetaCharsetParser::AttributeList attributes; - if (const NamedNodeMap* attributesMap = element->updatedAttributes()) { - for (unsigned i = 0; i < attributesMap->length(); ++i) { - Attribute* item = attributesMap->attributeItem(i); + if (element->hasAttributes()) { + for (unsigned i = 0; i < element->attributeCount(); ++i) { + Attribute* item = element->attributeItem(i); // FIXME: We should deal appropriately with the attribute if they have a namespace. attributes.append(make_pair(item->name().toString(), item->value().string())); } @@ -227,7 +227,7 @@ void PageSerializer::serializeFrame(Frame* frame) Element* element = toElement(node); // We have to process in-line style as it might contain some resources (typically background images). if (element->isStyledElement()) - retrieveResourcesForCSSDeclaration(static_cast<StyledElement*>(element)->inlineStyleDecl()); + retrieveResourcesForCSSDeclaration(static_cast<StyledElement*>(element)->inlineStyleDecl(), document); if (element->hasTagName(HTMLNames::imgTag)) { HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(element); @@ -263,10 +263,10 @@ void PageSerializer::serializeCSSStyleSheet(CSSStyleSheet* styleSheet, const KUR if (i < styleSheet->length() - 1) cssText.append("\n\n"); } + Document* document = styleSheet->findDocument(); // Some rules have resources associated with them that we need to retrieve. if (rule->isImportRule()) { - CSSImportRule* importRule = static_cast<CSSImportRule*>(rule); - Document* document = styleSheet->findDocument(); + CSSImportRule* importRule = static_cast<CSSImportRule*>(rule); KURL importURL = document->completeURL(importRule->href()); if (m_resourceURLs.contains(importURL)) continue; @@ -275,7 +275,7 @@ void PageSerializer::serializeCSSStyleSheet(CSSStyleSheet* styleSheet, const KUR // FIXME: Add support for font face rule. It is not clear to me at this point if the actual otf/eot file can // be retrieved from the CSSFontFaceRule object. } else if (rule->isStyleRule()) - retrieveResourcesForCSSRule(static_cast<CSSStyleRule*>(rule)); + retrieveResourcesForCSSRule(static_cast<CSSStyleRule*>(rule), document); } if (url.isValid() && !m_resourceURLs.contains(url)) { @@ -302,19 +302,16 @@ void PageSerializer::addImageToResources(CachedImage* image, RenderObject* image m_resourceURLs.add(url); } -void PageSerializer::retrieveResourcesForCSSRule(CSSStyleRule* rule) +void PageSerializer::retrieveResourcesForCSSRule(CSSStyleRule* rule, Document* document) { - retrieveResourcesForCSSDeclaration(rule->declaration()); + retrieveResourcesForCSSDeclaration(rule->declaration(), document); } -void PageSerializer::retrieveResourcesForCSSDeclaration(CSSMutableStyleDeclaration* styleDeclaration) +void PageSerializer::retrieveResourcesForCSSDeclaration(StylePropertySet* styleDeclaration, Document* document) { if (!styleDeclaration) return; - CSSStyleSheet* cssStyleSheet = styleDeclaration->parentStyleSheet(); - ASSERT(cssStyleSheet); - // The background-image and list-style-image (for ul or ol) are the CSS properties // that make use of images. We iterate to make sure we include any other // image properties there might be. @@ -332,7 +329,6 @@ void PageSerializer::retrieveResourcesForCSSDeclaration(CSSMutableStyleDeclarati CachedImage* image = static_cast<StyleCachedImage*>(styleImage)->cachedImage(); - Document* document = cssStyleSheet->findDocument(); KURL url = document->completeURL(image->url()); addImageToResources(image, 0, url); } diff --git a/Source/WebCore/page/PageSerializer.h b/Source/WebCore/page/PageSerializer.h index d92ef20ab..a900f150a 100644 --- a/Source/WebCore/page/PageSerializer.h +++ b/Source/WebCore/page/PageSerializer.h @@ -41,12 +41,13 @@ namespace WebCore { class CachedImage; -class CSSMutableStyleDeclaration; class CSSStyleRule; class CSSStyleSheet; +class Document; class Frame; class Page; class RenderObject; +class StylePropertySet; // This class is used to serialize a page contents back to text (typically HTML). // It serializes all the page frames and retrieves resources such as images and CSS stylesheets. @@ -77,8 +78,8 @@ private: void serializeCSSStyleSheet(CSSStyleSheet*, const KURL&); void addImageToResources(CachedImage*, RenderObject*, const KURL&); - void retrieveResourcesForCSSDeclaration(CSSMutableStyleDeclaration*); - void retrieveResourcesForCSSRule(CSSStyleRule*); + void retrieveResourcesForCSSDeclaration(StylePropertySet*, Document*); + void retrieveResourcesForCSSRule(CSSStyleRule*, Document*); Vector<Resource>* m_resources; ListHashSet<KURL> m_resourceURLs; diff --git a/Source/WebCore/page/PrintContext.cpp b/Source/WebCore/page/PrintContext.cpp index abb417128..0af0bb576 100644 --- a/Source/WebCore/page/PrintContext.cpp +++ b/Source/WebCore/page/PrintContext.cpp @@ -249,8 +249,8 @@ int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSi scaledPageSize.scale(frame->view()->contentsSize().width() / pageRect.width()); printContext.computePageRectsWithPageSize(scaledPageSize, false); - int top = box->offsetTop(); - int left = box->offsetLeft(); + int top = box->pixelSnappedOffsetTop(); + int left = box->pixelSnappedOffsetLeft(); size_t pageNumber = 0; for (; pageNumber < printContext.pageCount(); pageNumber++) { const IntRect& page = printContext.pageRect(pageNumber); diff --git a/Source/WebCore/page/Screen.idl b/Source/WebCore/page/Screen.idl index 4471617b1..588060914 100644 --- a/Source/WebCore/page/Screen.idl +++ b/Source/WebCore/page/Screen.idl @@ -30,7 +30,7 @@ module window { interface [ - GenerateIsReachable=ImplFrame, + JSGenerateIsReachable=ImplFrame, OmitConstructor ] Screen { readonly attribute unsigned long height; diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index 599cb3110..b5cb963bb 100644 --- a/Source/WebCore/page/Settings.cpp +++ b/Source/WebCore/page/Settings.cpp @@ -189,6 +189,7 @@ Settings::Settings(Page* page) , m_showRepaintCounter(false) , m_experimentalNotificationsEnabled(false) , m_webGLEnabled(false) + , m_webGLErrorsToConsoleEnabled(false) , m_openGLMultisamplingEnabled(true) , m_privilegedWebGLExtensionsEnabled(false) , m_webAudioEnabled(false) @@ -240,6 +241,9 @@ Settings::Settings(Page* page) , m_scrollingCoordinatorEnabled(false) #endif , m_notificationsEnabled(true) +#if ENABLE(TOUCH_EVENTS) + , m_touchEventEmulationEnabled(false) +#endif , m_loadsImagesAutomaticallyTimer(this, &Settings::loadsImagesAutomaticallyTimerFired) { // A Frame may not have been created yet, so we initialize the AtomicString @@ -803,6 +807,11 @@ void Settings::setWebGLEnabled(bool enabled) m_webGLEnabled = enabled; } +void Settings::setWebGLErrorsToConsoleEnabled(bool enabled) +{ + m_webGLErrorsToConsoleEnabled = enabled; +} + void Settings::setOpenGLMultisamplingEnabled(bool enabled) { m_openGLMultisamplingEnabled = enabled; diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 5ef8eea7f..3a1406601 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -357,6 +357,9 @@ namespace WebCore { void setWebGLEnabled(bool); bool webGLEnabled() const { return m_webGLEnabled; } + void setWebGLErrorsToConsoleEnabled(bool); + bool webGLErrorsToConsoleEnabled() const { return m_webGLErrorsToConsoleEnabled; } + void setOpenGLMultisamplingEnabled(bool); bool openGLMultisamplingEnabled() const { return m_openGLMultisamplingEnabled; } @@ -523,6 +526,11 @@ namespace WebCore { void setNotificationsEnabled(bool enabled) { m_notificationsEnabled = enabled; } bool notificationsEnabled() const { return m_notificationsEnabled; } +#if ENABLE(TOUCH_EVENTS) + void setTouchEventEmulationEnabled(bool enabled) { m_touchEventEmulationEnabled = enabled; } + bool isTouchEventEmulationEnabled() const { return m_touchEventEmulationEnabled; } +#endif + private: Settings(Page*); @@ -618,6 +626,7 @@ namespace WebCore { bool m_showRepaintCounter : 1; bool m_experimentalNotificationsEnabled : 1; bool m_webGLEnabled : 1; + bool m_webGLErrorsToConsoleEnabled : 1; bool m_openGLMultisamplingEnabled : 1; bool m_privilegedWebGLExtensionsEnabled : 1; bool m_webAudioEnabled : 1; @@ -669,6 +678,10 @@ namespace WebCore { bool m_notificationsEnabled : 1; +#if ENABLE(TOUCH_EVENTS) + bool m_touchEventEmulationEnabled : 1; +#endif + Timer<Settings> m_loadsImagesAutomaticallyTimer; void loadsImagesAutomaticallyTimerFired(Timer<Settings>*); diff --git a/Source/WebCore/page/SpeechInputResultList.idl b/Source/WebCore/page/SpeechInputResultList.idl index 5a23d4f02..b9213d002 100644 --- a/Source/WebCore/page/SpeechInputResultList.idl +++ b/Source/WebCore/page/SpeechInputResultList.idl @@ -26,7 +26,7 @@ module core { interface [ - HasIndexGetter, + IndexedGetter, Conditional=INPUT_SPEECH ] SpeechInputResultList { readonly attribute unsigned long length; diff --git a/Source/WebCore/page/WebKitAnimation.cpp b/Source/WebCore/page/WebKitAnimation.cpp index b757d2317..98e77367c 100644 --- a/Source/WebCore/page/WebKitAnimation.cpp +++ b/Source/WebCore/page/WebKitAnimation.cpp @@ -84,9 +84,18 @@ bool WebKitAnimation::ended() const WebKitAnimation::Direction WebKitAnimation::direction() const { - if (m_keyframeAnimation->animation()->direction() == Animation::AnimationDirectionNormal) + switch (m_keyframeAnimation->animation()->direction()) { + case Animation::AnimationDirectionNormal: return DIRECTION_NORMAL; - return DIRECTION_ALTERNATE; + case Animation::AnimationDirectionAlternate: + return DIRECTION_ALTERNATE; + case Animation::AnimationDirectionReverse: + return DIRECTION_REVERSE; + case Animation::AnimationDirectionAlternateReverse: + return DIRECTION_ALTERNATE_REVERSE; + } + ASSERT_NOT_REACHED(); + return DIRECTION_NORMAL; } WebKitAnimation::FillMode WebKitAnimation::fillMode() const diff --git a/Source/WebCore/page/WebKitAnimation.h b/Source/WebCore/page/WebKitAnimation.h index 6bea1e5d4..bef74382a 100644 --- a/Source/WebCore/page/WebKitAnimation.h +++ b/Source/WebCore/page/WebKitAnimation.h @@ -59,7 +59,7 @@ public: bool ended() const; // direction - enum Direction { DIRECTION_NORMAL, DIRECTION_ALTERNATE }; + enum Direction { DIRECTION_NORMAL, DIRECTION_ALTERNATE, DIRECTION_REVERSE, DIRECTION_ALTERNATE_REVERSE }; Direction direction() const; // fill mode diff --git a/Source/WebCore/page/WebKitAnimationList.idl b/Source/WebCore/page/WebKitAnimationList.idl index 72172a70a..ed305f792 100644 --- a/Source/WebCore/page/WebKitAnimationList.idl +++ b/Source/WebCore/page/WebKitAnimationList.idl @@ -26,7 +26,7 @@ module html { interface [ - HasIndexGetter + IndexedGetter ] WebKitAnimationList { readonly attribute unsigned long length; WebKitAnimation item(in unsigned long index); diff --git a/Source/WebCore/page/WorkerNavigator.idl b/Source/WebCore/page/WorkerNavigator.idl index 1544f155e..819de09d6 100644 --- a/Source/WebCore/page/WorkerNavigator.idl +++ b/Source/WebCore/page/WorkerNavigator.idl @@ -30,8 +30,8 @@ module threads { interface [ Conditional=WORKERS, - GenerateIsReachable=Impl, - NoStaticTables, + JSGenerateIsReachable=Impl, + JSNoStaticTables, OmitConstructor ] WorkerNavigator { readonly attribute DOMString appName; diff --git a/Source/WebCore/page/animation/AnimationBase.cpp b/Source/WebCore/page/animation/AnimationBase.cpp index e3ad92fa0..4fd0409ec 100644 --- a/Source/WebCore/page/animation/AnimationBase.cpp +++ b/Source/WebCore/page/animation/AnimationBase.cpp @@ -1673,7 +1673,9 @@ double AnimationBase::fractionalTime(double scale, double elapsedTime, double of integralTime = min(integralTime, m_animation->iterationCount() - 1); fractionalTime -= integralTime; - if ((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1)) + if (((m_animation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1)) + || ((m_animation->direction() == Animation::AnimationDirectionAlternateReverse) && !(integralTime & 1)) + || m_animation->direction() == Animation::AnimationDirectionReverse) fractionalTime = 1 - fractionalTime; if (scale != 1 || offset) diff --git a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp index c83bcb4aa..e569b2c25 100644 --- a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp +++ b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp @@ -34,7 +34,11 @@ #include "IntRect.h" #include "Page.h" #include "PlatformWheelEvent.h" +#include "Region.h" #include "ScrollAnimator.h" +#include "ScrollingThread.h" +#include "ScrollingTree.h" +#include "ScrollingTreeState.h" #include <wtf/Functional.h> #include <wtf/MainThread.h> #include <wtf/PassRefPtr.h> @@ -48,19 +52,31 @@ PassRefPtr<ScrollingCoordinator> ScrollingCoordinator::create(Page* page) ScrollingCoordinator::ScrollingCoordinator(Page* page) : m_page(page) - , m_didDispatchDidUpdateMainFrameScrollPosition(false) + , m_scrollingTree(ScrollingTree::create(this)) + , m_scrollingTreeState(ScrollingTreeState::create()) + , m_scrollingTreeStateCommitterTimer(this, &ScrollingCoordinator::scrollingTreeStateCommitterTimerFired) { } ScrollingCoordinator::~ScrollingCoordinator() { ASSERT(!m_page); + ASSERT(!m_scrollingTree); } void ScrollingCoordinator::pageDestroyed() { ASSERT(m_page); m_page = 0; + + // Invalidating the scrolling tree will break the reference cycle between the ScrollingCoordinator and ScrollingTree objects. + ScrollingThread::dispatch(bind(&ScrollingTree::invalidate, m_scrollingTree.release())); +} + +ScrollingTree* ScrollingCoordinator::scrollingTree() const +{ + ASSERT(m_scrollingTree); + return m_scrollingTree.get(); } bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView) const @@ -75,78 +91,103 @@ bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView return true; } -void ScrollingCoordinator::syncFrameViewGeometry(FrameView* frameView) +void ScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView) { ASSERT(isMainThread()); ASSERT(m_page); - if (frameView->frame() != m_page->mainFrame()) + if (!coordinatesScrollingForFrameView(frameView)) return; - IntRect visibleContentRect = frameView->visibleContentRect(); - IntSize contentsSize = frameView->contentsSize(); + // Compute the region of the page that we can't do fast scrolling for. This currently includes + // all scrollable areas, such as subframes, overflow divs and list boxes. + Region nonScrollableRegion; + if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) { + for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) { + ScrollableArea* scrollableArea = *it; - MutexLocker locker(m_mainFrameGeometryMutex); - if (m_mainFrameVisibleContentRect == visibleContentRect && m_mainFrameContentsSize == contentsSize) - return; + // Check if this area can be scrolled at all. + if ((!scrollableArea->horizontalScrollbar() || !scrollableArea->horizontalScrollbar()->enabled()) + && (!scrollableArea->verticalScrollbar() || !scrollableArea->verticalScrollbar()->enabled())) + continue; - m_mainFrameVisibleContentRect = visibleContentRect; - m_mainFrameContentsSize = contentsSize; + nonScrollableRegion.unite(scrollableArea->scrollableAreaBoundingBox()); + } + } - // FIXME: Inform the scrolling thread that the frame geometry has changed. + m_scrollingTreeState->setViewportRect(IntRect(IntPoint(), frameView->visibleContentRect().size())); + m_scrollingTreeState->setContentsSize(frameView->contentsSize()); + m_scrollingTreeState->setNonFastScrollableRegion(nonScrollableRegion); + scheduleTreeStateCommit(); } -bool ScrollingCoordinator::handleWheelEvent(const PlatformWheelEvent& wheelEvent) +void ScrollingCoordinator::frameViewWheelEventHandlerCountChanged(FrameView*) { - // FIXME: Check for wheel event handlers. - // FIXME: Check if we're over a subframe or overflow div. - // FIXME: As soon as we've determined that we can handle the wheel event, we should do the - // bulk of the work on the scrolling thread and return from this function. - // FIXME: Handle rubberbanding. - float deltaX = wheelEvent.deltaX(); - float deltaY = wheelEvent.deltaY(); - - // Slightly prefer scrolling vertically by applying the = case to deltaY - if (fabsf(deltaY) >= fabsf(deltaX)) - deltaX = 0; - else - deltaY = 0; - - IntSize scrollOffset = IntSize(-deltaX, -deltaY); - dispatchOnScrollingThread(bind(&ScrollingCoordinator::scrollByOnScrollingThread, this, scrollOffset)); - return true; -} + ASSERT(isMainThread()); + ASSERT(m_page); -#if ENABLE(GESTURE_EVENTS) -bool ScrollingCoordinator::handleGestureEvent(const PlatformGestureEvent&) -{ - // FIXME: Implement. - return false; + recomputeWheelEventHandlerCount(); } -#endif -void ScrollingCoordinator::didUpdateMainFrameScrollPosition() +void ScrollingCoordinator::updateMainFrameScrollPosition(const IntPoint& scrollPosition) { ASSERT(isMainThread()); if (!m_page) return; - IntPoint scrollPosition; + FrameView* frameView = m_page->mainFrame()->view(); + if (!frameView) + return; - { - MutexLocker locker(m_mainFrameGeometryMutex); - ASSERT(m_didDispatchDidUpdateMainFrameScrollPosition); + frameView->setConstrainsScrollingToContentEdge(false); + frameView->scrollToOffsetWithoutAnimation(scrollPosition); + frameView->setConstrainsScrollingToContentEdge(true); +} - scrollPosition = m_mainFrameScrollPosition; - m_didDispatchDidUpdateMainFrameScrollPosition = false; +void ScrollingCoordinator::recomputeWheelEventHandlerCount() +{ + unsigned wheelEventHandlerCount = 0; + for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + if (frame->document()) + wheelEventHandlerCount += frame->document()->wheelEventHandlerCount(); } - if (FrameView* frameView = m_page->mainFrame()->view()) { - frameView->setConstrainsScrollingToContentEdge(false); - frameView->scrollToOffsetWithoutAnimation(scrollPosition); - frameView->setConstrainsScrollingToContentEdge(true); - } + m_scrollingTreeState->setWheelEventHandlerCount(wheelEventHandlerCount); + scheduleTreeStateCommit(); +} + +void ScrollingCoordinator::scheduleTreeStateCommit() +{ + if (m_scrollingTreeStateCommitterTimer.isActive()) + return; + + if (!m_scrollingTreeState->hasChangedProperties()) + return; + + m_scrollingTreeStateCommitterTimer.startOneShot(0); +} + +void ScrollingCoordinator::scrollingTreeStateCommitterTimerFired(Timer<ScrollingCoordinator>*) +{ + commitTreeState(); +} + +void ScrollingCoordinator::commitTreeStateIfNeeded() +{ + if (!m_scrollingTreeState->hasChangedProperties()) + return; + + commitTreeState(); + m_scrollingTreeStateCommitterTimer.stop(); +} + +void ScrollingCoordinator::commitTreeState() +{ + ASSERT(m_scrollingTreeState->hasChangedProperties()); + + OwnPtr<ScrollingTreeState> treeState = m_scrollingTreeState->commit(); + ScrollingThread::dispatch(bind(&ScrollingTree::commitNewTreeState, m_scrollingTree.get(), treeState.release())); } } // namespace WebCore diff --git a/Source/WebCore/page/scrolling/ScrollingCoordinator.h b/Source/WebCore/page/scrolling/ScrollingCoordinator.h index e295d8031..eb597b8b0 100644 --- a/Source/WebCore/page/scrolling/ScrollingCoordinator.h +++ b/Source/WebCore/page/scrolling/ScrollingCoordinator.h @@ -30,6 +30,7 @@ #include "GraphicsLayer.h" #include "IntRect.h" +#include "Timer.h" #include <wtf/Forward.h> #include <wtf/ThreadSafeRefCounted.h> #include <wtf/Threading.h> @@ -44,6 +45,8 @@ class FrameView; class GraphicsLayer; class Page; class PlatformWheelEvent; +class ScrollingTree; +class ScrollingTreeState; #if ENABLE(GESTURE_EVENTS) class PlatformGestureEvent; @@ -56,9 +59,18 @@ public: void pageDestroyed(); + ScrollingTree* scrollingTree() const; + // Return whether this scrolling coordinator handles scrolling for the given frame view. bool coordinatesScrollingForFrameView(FrameView*) const; + // Should be called whenever the given frame view has been laid out. + void frameViewLayoutUpdated(FrameView*); + + // Should be called whenever a wheel event handler is added or removed in the + // frame view's underlying document. + void frameViewWheelEventHandlerCountChanged(FrameView*); + // Should be called whenever the scroll layer for the given frame view changes. void frameViewScrollLayerDidChange(FrameView*, const GraphicsLayer*); @@ -68,49 +80,24 @@ public: // Should be called whenever the horizontal scrollbar layer for the given frame view changes. void frameViewVerticalScrollbarLayerDidChange(FrameView*, GraphicsLayer* verticalScrollbarLayer); - // Should be called whenever the geometry of the given frame view changes, - // including the visible content rect and the content size. - void syncFrameViewGeometry(FrameView*); - - // Can be called from any thread. Will try to handle the wheel event on the scrolling thread, - // and return false if the event must be sent again to the WebCore event handler. - bool handleWheelEvent(const PlatformWheelEvent&); - -#if ENABLE(GESTURE_EVENTS) - // Can be called from any thread. Will try to handle the gesture event on the scrolling thread, - // and return false if the event must be sent again to the WebCore event handler. - bool handleGestureEvent(const PlatformGestureEvent&); -#endif + // Dispatched by the scrolling tree whenever the main frame scroll position changes. + void updateMainFrameScrollPosition(const IntPoint&); private: explicit ScrollingCoordinator(Page*); - // FIXME: Once we have a proper thread/run loop abstraction we should get rid of these - // functions and just use something like scrollingRunLoop()->dispatch(function); - static bool isScrollingThread(); - static void dispatchOnScrollingThread(const Function<void()>&); + void recomputeWheelEventHandlerCount(); - // The following functions can only be called from the main thread. - void didUpdateMainFrameScrollPosition(); + void scheduleTreeStateCommit(); + void scrollingTreeStateCommitterTimerFired(Timer<ScrollingCoordinator>*); + void commitTreeStateIfNeeded(); + void commitTreeState(); - // The following functions can only be called from the scrolling thread. - void scrollByOnScrollingThread(const IntSize& offset); - - // This function must be called with the main frame geometry mutex held. - void updateMainFrameScrollLayerPositionOnScrollingThread(const FloatPoint&); - -private: Page* m_page; + RefPtr<ScrollingTree> m_scrollingTree; - Mutex m_mainFrameGeometryMutex; - IntRect m_mainFrameVisibleContentRect; - IntSize m_mainFrameContentsSize; -#if PLATFORM(MAC) - RetainPtr<PlatformLayer> m_mainFrameScrollLayer; -#endif - - bool m_didDispatchDidUpdateMainFrameScrollPosition; - IntPoint m_mainFrameScrollPosition; + OwnPtr<ScrollingTreeState> m_scrollingTreeState; + Timer<ScrollingCoordinator> m_scrollingTreeStateCommitterTimer; }; } // namespace WebCore diff --git a/Source/WebCore/page/scrolling/ScrollingThread.cpp b/Source/WebCore/page/scrolling/ScrollingThread.cpp new file mode 100644 index 000000000..fc5a405da --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingThread.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingThread.h" + +#if ENABLE(THREADED_SCROLLING) + +namespace WebCore { + +ScrollingThread::ScrollingThread() + : m_threadIdentifier(0) +{ +} + +bool ScrollingThread::isCurrentThread() +{ + if (!shared().m_threadIdentifier) + return false; + + return currentThread() == shared().m_threadIdentifier; +} + +void ScrollingThread::dispatch(const Function<void()>& function) +{ + shared().createThreadIfNeeded(); + + { + MutexLocker locker(shared().m_functionsMutex); + shared().m_functions.append(function); + } + + shared().wakeUpRunLoop(); +} + +ScrollingThread& ScrollingThread::shared() +{ + DEFINE_STATIC_LOCAL(ScrollingThread, scrollingThread, ()); + return scrollingThread; +} + +void ScrollingThread::createThreadIfNeeded() +{ + if (m_threadIdentifier) + return; + + m_threadIdentifier = createThread(threadCallback, this, "WebCore: Scrolling"); + + // Wait for the thread to initialize the run loop. + { + MutexLocker locker(m_initializeRunLoopConditionMutex); + + while (!m_threadRunLoop) + m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex); + } +} + +void* ScrollingThread::threadCallback(void* scrollingThread) +{ + static_cast<ScrollingThread*>(scrollingThread)->threadBody(); + + return 0; +} + +void ScrollingThread::threadBody() +{ + ASSERT(isCurrentThread()); + + initializeRunLoop(); +} + +void ScrollingThread::dispatchFunctionsFromScrollingThread() +{ + ASSERT(isCurrentThread()); + + Vector<Function<void()> > functions; + + { + MutexLocker locker(m_functionsMutex); + m_functions.swap(functions); + } + + for (size_t i = 0; i < functions.size(); ++i) + functions[i](); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/ScrollingThread.h b/Source/WebCore/page/scrolling/ScrollingThread.h new file mode 100644 index 000000000..22671e4f5 --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingThread.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollingThread_h +#define ScrollingThread_h + +#if ENABLE(THREADED_SCROLLING) + +#include <wtf/Functional.h> +#include <wtf/Noncopyable.h> +#include <wtf/Threading.h> +#include <wtf/Vector.h> + +#if PLATFORM(MAC) +#include <wtf/RetainPtr.h> +#endif + +namespace WebCore { + +class ScrollingThread { + WTF_MAKE_NONCOPYABLE(ScrollingThread); + +public: + static bool isCurrentThread(); + static void dispatch(const Function<void()>&); + +private: + ScrollingThread(); + + static ScrollingThread& shared(); + + void createThreadIfNeeded(); + static void* threadCallback(void* scrollingThread); + void threadBody(); + void dispatchFunctionsFromScrollingThread(); + + void initializeRunLoop(); + void wakeUpRunLoop(); + +#if PLATFORM(MAC) + static void threadRunLoopSourceCallback(void* scrollingThread); + void threadRunLoopSourceCallback(); +#endif + + ThreadIdentifier m_threadIdentifier; + + ThreadCondition m_initializeRunLoopCondition; + Mutex m_initializeRunLoopConditionMutex; + + Mutex m_functionsMutex; + Vector<Function<void()> > m_functions; + +#if PLATFORM(MAC) + // FIXME: We should use WebCore::RunLoop here. + RetainPtr<CFRunLoopRef> m_threadRunLoop; + RetainPtr<CFRunLoopSourceRef> m_threadRunLoopSource; +#endif +}; + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) + +#endif // ScrollingThread_h diff --git a/Source/WebCore/page/scrolling/ScrollingTree.cpp b/Source/WebCore/page/scrolling/ScrollingTree.cpp new file mode 100644 index 000000000..bc1c50d9f --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTree.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingTree.h" + +#if ENABLE(THREADED_SCROLLING) + +#include "PlatformWheelEvent.h" +#include "ScrollingCoordinator.h" +#include "ScrollingThread.h" +#include "ScrollingTreeNode.h" +#include "ScrollingTreeState.h" +#include <wtf/MainThread.h> + +namespace WebCore { + +PassRefPtr<ScrollingTree> ScrollingTree::create(ScrollingCoordinator* scrollingCoordinator) +{ + return adoptRef(new ScrollingTree(scrollingCoordinator)); +} + +ScrollingTree::ScrollingTree(ScrollingCoordinator* scrollingCoordinator) + : m_scrollingCoordinator(scrollingCoordinator) + , m_rootNode(ScrollingTreeNode::create(this)) + , m_hasWheelEventHandlers(false) +{ +} + +ScrollingTree::~ScrollingTree() +{ + ASSERT(!m_scrollingCoordinator); +} + +bool ScrollingTree::tryToHandleWheelEvent(const PlatformWheelEvent& wheelEvent) +{ + { + MutexLocker lock(m_mutex); + + if (m_hasWheelEventHandlers) + return false; + + if (!m_nonFastScrollableRegion.isEmpty()) { + // FIXME: This is not correct for non-default scroll origins. + IntPoint position = wheelEvent.position(); + position.moveBy(m_mainFrameScrollPosition); + if (m_nonFastScrollableRegion.contains(position)) + return false; + } + } + + ScrollingThread::dispatch(bind(&ScrollingTree::handleWheelEvent, this, wheelEvent)); + return true; +} + +void ScrollingTree::handleWheelEvent(const PlatformWheelEvent& wheelEvent) +{ + ASSERT(ScrollingThread::isCurrentThread()); + + m_rootNode->handleWheelEvent(wheelEvent); +} + +void ScrollingTree::invalidate() +{ + // Invalidate is dispatched by the ScrollingCoordinator class on the ScrollingThread + // to break the reference cycle between ScrollingTree and ScrollingCoordinator when the + // ScrollingCoordinator's page is destroyed. + ASSERT(ScrollingThread::isCurrentThread()); + m_scrollingCoordinator = nullptr; +} + +void ScrollingTree::commitNewTreeState(PassOwnPtr<ScrollingTreeState> scrollingTreeState) +{ + ASSERT(ScrollingThread::isCurrentThread()); + + if (scrollingTreeState->changedProperties() & (ScrollingTreeState::WheelEventHandlerCount | ScrollingTreeState::NonFastScrollableRegion)) { + MutexLocker lock(m_mutex); + + if (scrollingTreeState->changedProperties() & ScrollingTreeState::WheelEventHandlerCount) + m_hasWheelEventHandlers = scrollingTreeState->wheelEventHandlerCount(); + if (scrollingTreeState->changedProperties() & ScrollingTreeState::NonFastScrollableRegion) + m_nonFastScrollableRegion = scrollingTreeState->nonFastScrollableRegion(); + } + + m_rootNode->update(scrollingTreeState.get()); +} + +void ScrollingTree::updateMainFrameScrollPosition(const IntPoint& scrollPosition) +{ + if (!m_scrollingCoordinator) + return; + + { + MutexLocker lock(m_mutex); + m_mainFrameScrollPosition = scrollPosition; + } + + callOnMainThread(bind(&ScrollingCoordinator::updateMainFrameScrollPosition, m_scrollingCoordinator.get(), scrollPosition)); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/ScrollingTree.h b/Source/WebCore/page/scrolling/ScrollingTree.h new file mode 100644 index 000000000..76cbfda0a --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTree.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollingTree_h +#define ScrollingTree_h + +#if ENABLE(THREADED_SCROLLING) + +#include "Region.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/ThreadSafeRefCounted.h> + +namespace WebCore { + +class IntPoint; +class PlatformWheelEvent; +class ScrollingCoordinator; +class ScrollingTreeNode; +class ScrollingTreeState; + +// The ScrollingTree class lives almost exclusively on the scrolling thread and manages the +// hierarchy of scrollable regions on the page. It's also responsible for dispatching events +// to the correct scrolling tree nodes or dispatching events back to the ScrollingCoordinator +// object on the main thread if they can't be handled on the scrolling thread for various reasons. +class ScrollingTree : public ThreadSafeRefCounted<ScrollingTree> { +public: + static PassRefPtr<ScrollingTree> create(ScrollingCoordinator*); + ~ScrollingTree(); + + // Can be called from any thread. Will try to handle the wheel event on the scrolling thread. + // Returns true if the wheel event can be handled on the scrolling thread and false if the + // event must be sent again to the WebCore event handler. + bool tryToHandleWheelEvent(const PlatformWheelEvent&); + + // Must be called from the scrolling thread. Handles the wheel event. + void handleWheelEvent(const PlatformWheelEvent&); + + void invalidate(); + void commitNewTreeState(PassOwnPtr<ScrollingTreeState>); + + void updateMainFrameScrollPosition(const IntPoint& scrollPosition); + +private: + explicit ScrollingTree(ScrollingCoordinator*); + + RefPtr<ScrollingCoordinator> m_scrollingCoordinator; + OwnPtr<ScrollingTreeNode> m_rootNode; + + Mutex m_mutex; + Region m_nonFastScrollableRegion; + IntPoint m_mainFrameScrollPosition; + bool m_hasWheelEventHandlers; +}; + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) + +#endif // ScrollingTree_h diff --git a/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp b/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp new file mode 100644 index 000000000..bd94f00dc --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTreeNode.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingTreeNode.h" + +#if ENABLE(THREADED_SCROLLING) + +#include "ScrollingTreeState.h" + +namespace WebCore { + +ScrollingTreeNode::ScrollingTreeNode(ScrollingTree* scrollingTree) + : m_scrollingTree(scrollingTree) +{ +} + +ScrollingTreeNode::~ScrollingTreeNode() +{ +} + +void ScrollingTreeNode::update(ScrollingTreeState* state) +{ + if (state->changedProperties() & ScrollingTreeState::ViewportRect) + m_viewportRect = state->viewportRect(); + + if (state->changedProperties() & ScrollingTreeState::ContentsSize) + m_contentsSize = state->contentsSize(); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/ScrollingTreeNode.h b/Source/WebCore/page/scrolling/ScrollingTreeNode.h new file mode 100644 index 000000000..d26293a89 --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTreeNode.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollingTreeNode_h +#define ScrollingTreeNode_h + +#if ENABLE(THREADED_SCROLLING) + +#include "IntRect.h" +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +class PlatformWheelEvent; +class ScrollingTree; +class ScrollingTreeState; + +class ScrollingTreeNode { +public: + static PassOwnPtr<ScrollingTreeNode> create(ScrollingTree*); + virtual ~ScrollingTreeNode(); + + virtual void update(ScrollingTreeState*); + virtual void handleWheelEvent(const PlatformWheelEvent&) = 0; + +protected: + explicit ScrollingTreeNode(ScrollingTree*); + + ScrollingTree* scrollingTree() const { return m_scrollingTree; } + const IntRect& viewportRect() const { return m_viewportRect; } + const IntSize& contentsSize() const { return m_contentsSize; } + +private: + ScrollingTree* m_scrollingTree; + + IntRect m_viewportRect; + IntSize m_contentsSize; +}; + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) + +#endif // ScrollingTreeNode_h diff --git a/Source/WebCore/page/scrolling/ScrollingTreeState.cpp b/Source/WebCore/page/scrolling/ScrollingTreeState.cpp new file mode 100644 index 000000000..c368152c3 --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTreeState.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingTreeState.h" + +#if ENABLE(THREADED_SCROLLING) + +namespace WebCore { + +PassOwnPtr<ScrollingTreeState> ScrollingTreeState::create() +{ + return adoptPtr(new ScrollingTreeState); +} + +ScrollingTreeState::ScrollingTreeState() + : m_changedProperties(0) + , m_wheelEventHandlerCount(0) +{ +} + +ScrollingTreeState::~ScrollingTreeState() +{ +} + +void ScrollingTreeState::setViewportRect(const IntRect& viewportRect) +{ + if (m_viewportRect == viewportRect) + return; + + m_viewportRect = viewportRect; + m_changedProperties |= ViewportRect; +} + +void ScrollingTreeState::setContentsSize(const IntSize& contentsSize) +{ + if (m_contentsSize == contentsSize) + return; + + m_contentsSize = contentsSize; + m_changedProperties |= ContentsSize; +} + +void ScrollingTreeState::setNonFastScrollableRegion(const Region& nonFastScrollableRegion) +{ + if (m_nonFastScrollableRegion == nonFastScrollableRegion) + return; + + m_nonFastScrollableRegion = nonFastScrollableRegion; + m_changedProperties |= NonFastScrollableRegion; +} + +void ScrollingTreeState::setWheelEventHandlerCount(unsigned wheelEventHandlerCount) +{ + if (m_wheelEventHandlerCount == wheelEventHandlerCount) + return; + + m_wheelEventHandlerCount = wheelEventHandlerCount; + m_changedProperties |= WheelEventHandlerCount; +} + +PassOwnPtr<ScrollingTreeState> ScrollingTreeState::commit() +{ + OwnPtr<ScrollingTreeState> treeState = adoptPtr(new ScrollingTreeState(*this)); + m_changedProperties = 0; + + return treeState.release(); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/ScrollingTreeState.h b/Source/WebCore/page/scrolling/ScrollingTreeState.h new file mode 100644 index 000000000..fde884922 --- /dev/null +++ b/Source/WebCore/page/scrolling/ScrollingTreeState.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollingTreeState_h +#define ScrollingTreeState_h + +#if ENABLE(THREADED_SCROLLING) + +#include "GraphicsLayer.h" +#include "IntRect.h" +#include "Region.h" +#include <wtf/PassOwnPtr.h> + +#if PLATFORM(MAC) +#include <wtf/RetainPtr.h> +#endif + +namespace WebCore { + +// The ScrollingTreeState object keeps track of the current state of scrolling related properties. +// Whenever any properties change, the scrolling coordinator will be informed and will update the state +// and schedule a timer that will clone the new state and send it over to the scrolling thread, avoiding locking. +// FIXME: Once we support fast scrolling in subframes, this will have to become a tree-like structure. +class ScrollingTreeState { +public: + static PassOwnPtr<ScrollingTreeState> create(); + ~ScrollingTreeState(); + + enum ChangedProperty { + ViewportRect = 1 << 0, + ContentsSize = 1 << 1, + NonFastScrollableRegion = 1 << 2, + WheelEventHandlerCount = 1 << 3, + ScrollLayer = 1 << 4, + }; + + bool hasChangedProperties() const { return m_changedProperties; } + unsigned changedProperties() const { return m_changedProperties; } + + const IntRect& viewportRect() const { return m_viewportRect; } + void setViewportRect(const IntRect&); + + const IntSize& contentsSize() const { return m_contentsSize; } + void setContentsSize(const IntSize&); + + const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } + void setNonFastScrollableRegion(const Region&); + + unsigned wheelEventHandlerCount() const { return m_wheelEventHandlerCount; } + void setWheelEventHandlerCount(unsigned); + + PlatformLayer* platformScrollLayer() const; + void setScrollLayer(const GraphicsLayer*); + + // Copies the current tree state and clears the changed properties mask in the original. + PassOwnPtr<ScrollingTreeState> commit(); + +private: + ScrollingTreeState(); + + unsigned m_changedProperties; + + IntRect m_viewportRect; + IntSize m_contentsSize; + + Region m_nonFastScrollableRegion; + + unsigned m_wheelEventHandlerCount; + +#if PLATFORM(MAC) + RetainPtr<PlatformLayer> m_platformScrollLayer; +#endif + +}; + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) + +#endif // ScrollingTreeState_h diff --git a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm index 00535d2b9..31fa76683 100644 --- a/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm +++ b/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm @@ -31,6 +31,8 @@ #import "FrameView.h" #import "Page.h" +#import "ScrollingThread.h" +#import "ScrollingTreeState.h" #import <QuartzCore/QuartzCore.h> #import <wtf/Functional.h> #import <wtf/MainThread.h> @@ -40,127 +42,6 @@ namespace WebCore { -class ScrollingThread { -public: - ScrollingThread() - : m_threadIdentifier(0) - { - } - - bool isCurrentThread() const; - void dispatch(const Function<void()>&); - -private: - void createThreadIfNeeded(); - - static void* threadCallback(void* scrollingThread); - void threadBody(); - - static void threadRunLoopSourceCallback(void* scrollingThread); - void threadRunLoopSourceCallback(); - - ThreadIdentifier m_threadIdentifier; - - ThreadCondition m_initializeRunLoopCondition; - Mutex m_initializeRunLoopConditionMutex; - - RetainPtr<CFRunLoopRef> m_threadRunLoop; - RetainPtr<CFRunLoopSourceRef> m_threadRunLoopSource; - - Mutex m_functionsMutex; - Vector<Function<void()> > m_functions; -}; - -bool ScrollingThread::isCurrentThread() const -{ - if (!m_threadIdentifier) - return false; - - return currentThread() == m_threadIdentifier; -} - -void ScrollingThread::createThreadIfNeeded() -{ - if (m_threadIdentifier) - return; - - m_threadIdentifier = createThread(threadCallback, this, "WebCore: Scrolling"); - - // Wait for the thread to initialize the run loop. - { - MutexLocker locker(m_initializeRunLoopConditionMutex); - - while (!m_threadRunLoop) - m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex); - } -} - -void* ScrollingThread::threadCallback(void* scrollingThread) -{ - static_cast<ScrollingThread*>(scrollingThread)->threadBody(); - - return 0; -} - -void ScrollingThread::threadBody() -{ - ASSERT(isCurrentThread()); - - // Initialize the run loop. - { - MutexLocker locker(m_initializeRunLoopConditionMutex); - - m_threadRunLoop = CFRunLoopGetCurrent(); - - CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, threadRunLoopSourceCallback }; - m_threadRunLoopSource = adoptCF(CFRunLoopSourceCreate(0, 0, &context)); - CFRunLoopAddSource(CFRunLoopGetCurrent(), m_threadRunLoopSource.get(), kCFRunLoopDefaultMode); - - m_initializeRunLoopCondition.broadcast(); - } - - CFRunLoopRun(); -} - -void ScrollingThread::threadRunLoopSourceCallback(void* scrollingThread) -{ - static_cast<ScrollingThread*>(scrollingThread)->threadRunLoopSourceCallback(); -} - -void ScrollingThread::threadRunLoopSourceCallback() -{ - ASSERT(isCurrentThread()); - - Vector<Function<void ()> > functions; - - { - MutexLocker locker(m_functionsMutex); - m_functions.swap(functions); - } - - for (size_t i = 0; i < functions.size(); ++i) - functions[i](); -} - -void ScrollingThread::dispatch(const Function<void()>& function) -{ - createThreadIfNeeded(); - - { - MutexLocker locker(m_functionsMutex); - m_functions.append(function); - } - - CFRunLoopSourceSignal(m_threadRunLoopSource.get()); - CFRunLoopWakeUp(m_threadRunLoop.get()); -} - -static ScrollingThread& scrollingThread() -{ - DEFINE_STATIC_LOCAL(ScrollingThread, scrollingThread, ()); - return scrollingThread; -} - void ScrollingCoordinator::frameViewHorizontalScrollbarLayerDidChange(FrameView* frameView, GraphicsLayer*) { ASSERT(isMainThread()); @@ -191,56 +72,8 @@ void ScrollingCoordinator::frameViewScrollLayerDidChange(FrameView* frameView, c if (frameView->frame() != m_page->mainFrame()) return; - MutexLocker locker(m_mainFrameGeometryMutex); - m_mainFrameScrollLayer = scrollLayer->platformLayer(); - - // FIXME: Inform the scrolling thread? -} - -bool ScrollingCoordinator::isScrollingThread() -{ - return scrollingThread().isCurrentThread(); -} - -void ScrollingCoordinator::dispatchOnScrollingThread(const Function<void()>& function) -{ - return scrollingThread().dispatch(function); -} - -void ScrollingCoordinator::scrollByOnScrollingThread(const IntSize& offset) -{ - ASSERT(isScrollingThread()); - - MutexLocker locker(m_mainFrameGeometryMutex); - - // FIXME: Should we cache the scroll position as well or always get it from the layer? - IntPoint scrollPosition = IntPoint([m_mainFrameScrollLayer.get() position]); - scrollPosition = -scrollPosition; - - scrollPosition += offset; - scrollPosition.clampNegativeToZero(); - - IntPoint maximumScrollPosition = IntPoint(m_mainFrameContentsSize.width() - m_mainFrameVisibleContentRect.width(), m_mainFrameContentsSize.height() - m_mainFrameVisibleContentRect.height()); - scrollPosition = scrollPosition.shrunkTo(maximumScrollPosition); - - updateMainFrameScrollLayerPositionOnScrollingThread(-scrollPosition); - - m_mainFrameScrollPosition = scrollPosition; - if (!m_didDispatchDidUpdateMainFrameScrollPosition) { - callOnMainThread(bind(&ScrollingCoordinator::didUpdateMainFrameScrollPosition, this)); - m_didDispatchDidUpdateMainFrameScrollPosition = true; - } -} - -void ScrollingCoordinator::updateMainFrameScrollLayerPositionOnScrollingThread(const FloatPoint& scrollLayerPosition) -{ - ASSERT(isScrollingThread()); - ASSERT(!m_mainFrameGeometryMutex.tryLock()); - - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - [m_mainFrameScrollLayer.get() setPosition:scrollLayerPosition]; - [CATransaction commit]; + m_scrollingTreeState->setScrollLayer(scrollLayer); + scheduleTreeStateCommit(); } } // namespace WebCore diff --git a/Source/WebCore/page/scrolling/mac/ScrollingThreadMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingThreadMac.mm new file mode 100644 index 000000000..a6a768113 --- /dev/null +++ b/Source/WebCore/page/scrolling/mac/ScrollingThreadMac.mm @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingThread.h" + +#if ENABLE(THREADED_SCROLLING) + +namespace WebCore { + +void ScrollingThread::initializeRunLoop() +{ + // Initialize the run loop. + { + MutexLocker locker(m_initializeRunLoopConditionMutex); + + m_threadRunLoop = CFRunLoopGetCurrent(); + + CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, threadRunLoopSourceCallback }; + m_threadRunLoopSource = adoptCF(CFRunLoopSourceCreate(0, 0, &context)); + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_threadRunLoopSource.get(), kCFRunLoopDefaultMode); + + m_initializeRunLoopCondition.broadcast(); + } + + CFRunLoopRun(); +} + +void ScrollingThread::wakeUpRunLoop() +{ + CFRunLoopSourceSignal(m_threadRunLoopSource.get()); + CFRunLoopWakeUp(m_threadRunLoop.get()); +} + +void ScrollingThread::threadRunLoopSourceCallback(void* scrollingThread) +{ + static_cast<ScrollingThread*>(scrollingThread)->threadRunLoopSourceCallback(); +} + +void ScrollingThread::threadRunLoopSourceCallback() +{ + dispatchFunctionsFromScrollingThread(); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.h b/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.h new file mode 100644 index 000000000..b1ae6ee76 --- /dev/null +++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollingTreeNodeMac_h +#define ScrollingTreeNodeMac_h + +#if ENABLE(THREADED_SCROLLING) + +#include "ScrollingTreeNode.h" +#include <wtf/RetainPtr.h> + +OBJC_CLASS CALayer; + +namespace WebCore { + +class ScrollingTreeNodeMac : public ScrollingTreeNode { +public: + explicit ScrollingTreeNodeMac(ScrollingTree*); + +private: + virtual void update(ScrollingTreeState*) OVERRIDE; + virtual void handleWheelEvent(const PlatformWheelEvent&) OVERRIDE; + + IntPoint scrollPosition() const; + void setScrollPosition(const IntPoint&); + + void scrollBy(const IntSize&); + + RetainPtr<CALayer> m_scrollLayer; +}; + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) + +#endif // ScrollingTreeNodeMac_h diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm new file mode 100644 index 000000000..76a8e3eaf --- /dev/null +++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeNodeMac.mm @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingTreeNodeMac.h" + +#if ENABLE(THREADED_SCROLLING) + +#include "PlatformWheelEvent.h" +#include "ScrollingTree.h" +#include "ScrollingTreeState.h" + +namespace WebCore { + +PassOwnPtr<ScrollingTreeNode> ScrollingTreeNode::create(ScrollingTree* scrollingTree) +{ + return adoptPtr(new ScrollingTreeNodeMac(scrollingTree)); +} + +ScrollingTreeNodeMac::ScrollingTreeNodeMac(ScrollingTree* scrollingTree) + : ScrollingTreeNode(scrollingTree) +{ +} + +void ScrollingTreeNodeMac::update(ScrollingTreeState* state) +{ + ScrollingTreeNode::update(state); + + if (state->changedProperties() & ScrollingTreeState::ScrollLayer) + m_scrollLayer = state->platformScrollLayer(); +} + +void ScrollingTreeNodeMac::handleWheelEvent(const PlatformWheelEvent& wheelEvent) +{ + // FXIME: This needs to handle rubberbanding. + scrollBy(IntSize(-wheelEvent.deltaX(), -wheelEvent.deltaY())); +} + +IntPoint ScrollingTreeNodeMac::scrollPosition() const +{ + CGPoint scrollLayerPosition = m_scrollLayer.get().position; + return IntPoint(-scrollLayerPosition.x, -scrollLayerPosition.y); +} + +void ScrollingTreeNodeMac::setScrollPosition(const IntPoint& position) +{ + m_scrollLayer.get().position = CGPointMake(-position.x(), -position.y()); +} + +void ScrollingTreeNodeMac::scrollBy(const IntSize &offset) +{ + setScrollPosition(scrollPosition() + offset); + + scrollingTree()->updateMainFrameScrollPosition(scrollPosition()); +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/scrolling/mac/ScrollingTreeStateMac.mm b/Source/WebCore/page/scrolling/mac/ScrollingTreeStateMac.mm new file mode 100644 index 000000000..21f0c7253 --- /dev/null +++ b/Source/WebCore/page/scrolling/mac/ScrollingTreeStateMac.mm @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollingTreeState.h" + +#if ENABLE(THREADED_SCROLLING) + +namespace WebCore { + +PlatformLayer* ScrollingTreeState::platformScrollLayer() const +{ + return m_platformScrollLayer.get(); +} + +void ScrollingTreeState::setScrollLayer(const GraphicsLayer* graphicsLayer) +{ + PlatformLayer* platformScrollLayer = graphicsLayer ? graphicsLayer->platformLayer() : nil; + + if (m_platformScrollLayer == platformScrollLayer) + return; + + m_platformScrollLayer = platformScrollLayer; + m_changedProperties |= ScrollLayer; +} + +} // namespace WebCore + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebCore/page/win/FrameCGWin.cpp b/Source/WebCore/page/win/FrameCGWin.cpp index 39f8d0a6b..ea2c391e7 100644 --- a/Source/WebCore/page/win/FrameCGWin.cpp +++ b/Source/WebCore/page/win/FrameCGWin.cpp @@ -97,7 +97,7 @@ DragImageRef Frame::nodeImage(Node* node) if (!renderer) return 0; - IntRect topLevelRect; + LayoutRect topLevelRect; IntRect paintingRect = renderer->paintingRootRect(topLevelRect); document()->updateLayout(); |