diff options
Diffstat (limited to 'Source/WebCore/page/mac')
-rw-r--r-- | Source/WebCore/page/mac/ChromeMac.mm | 52 | ||||
-rw-r--r-- | Source/WebCore/page/mac/DragControllerMac.mm | 81 | ||||
-rw-r--r-- | Source/WebCore/page/mac/EventHandlerMac.mm | 790 | ||||
-rw-r--r-- | Source/WebCore/page/mac/FrameMac.mm | 364 | ||||
-rw-r--r-- | Source/WebCore/page/mac/PageMac.cpp | 77 | ||||
-rw-r--r-- | Source/WebCore/page/mac/WebCoreFrameView.h | 42 | ||||
-rw-r--r-- | Source/WebCore/page/mac/WebCoreKeyboardUIMode.h | 40 | ||||
-rw-r--r-- | Source/WebCore/page/mac/WebCoreViewFactory.h | 54 | ||||
-rw-r--r-- | Source/WebCore/page/mac/WebCoreViewFactory.m | 48 |
9 files changed, 1548 insertions, 0 deletions
diff --git a/Source/WebCore/page/mac/ChromeMac.mm b/Source/WebCore/page/mac/ChromeMac.mm new file mode 100644 index 0000000..d2ae39d --- /dev/null +++ b/Source/WebCore/page/mac/ChromeMac.mm @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#import "config.h" +#import "Chrome.h" + +#import "BlockExceptions.h" +#import "ChromeClient.h" + +namespace WebCore { + + +void Chrome::focusNSView(NSView* view) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSResponder *firstResponder = client()->firstResponder(); + if (firstResponder == view) + return; + + if (![view window] || ![view superview] || ![view acceptsFirstResponder]) + return; + + client()->makeFirstResponder(view); + + // Setting focus can actually cause a style change which might + // remove the view from its superview while it's being made + // first responder. This confuses AppKit so we must restore + // the old first responder. + if (![view superview]) + client()->makeFirstResponder(firstResponder); + + END_BLOCK_OBJC_EXCEPTIONS; +} + +} // namespace WebCore diff --git a/Source/WebCore/page/mac/DragControllerMac.mm b/Source/WebCore/page/mac/DragControllerMac.mm new file mode 100644 index 0000000..05c8e09 --- /dev/null +++ b/Source/WebCore/page/mac/DragControllerMac.mm @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "DragController.h" + +#if ENABLE(DRAG_SUPPORT) +#import "DragData.h" +#import "Frame.h" +#import "FrameView.h" +#import "Page.h" + +namespace WebCore { + +const int DragController::LinkDragBorderInset = -2; + +const int DragController::MaxOriginalImageArea = 1500 * 1500; +const int DragController::DragIconRightInset = 7; +const int DragController::DragIconBottomInset = 3; + +const float DragController::DragImageAlpha = 0.75f; + +bool DragController::isCopyKeyDown() +{ + return [[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask; +} + +DragOperation DragController::dragOperation(DragData* dragData) +{ + ASSERT(dragData); + if ([NSApp modalWindow] || !dragData->containsURL()) + return DragOperationNone; + + if (!m_documentUnderMouse || (![[m_page->mainFrame()->view()->getOuterView() window] attachedSheet] + && [dragData->platformData() draggingSource] != m_page->mainFrame()->view()->getOuterView())) + return DragOperationCopy; + + return DragOperationNone; +} + +const IntSize& DragController::maxDragImageSize() +{ + static const IntSize maxDragImageSize(400, 400); + + return maxDragImageSize; +} + +void DragController::cleanupAfterSystemDrag() +{ + // Drag has ended, dragEnded *should* have been called, however it is possible + // for the UIDelegate to take over the drag, and fail to send the appropriate + // drag termination event. As dragEnded just resets drag variables, we just + // call it anyway to be on the safe side + dragEnded(); +} + +} // namespace WebCore + +#endif // ENABLE(DRAG_SUPPORT) diff --git a/Source/WebCore/page/mac/EventHandlerMac.mm b/Source/WebCore/page/mac/EventHandlerMac.mm new file mode 100644 index 0000000..2d4d86b --- /dev/null +++ b/Source/WebCore/page/mac/EventHandlerMac.mm @@ -0,0 +1,790 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "EventHandler.h" + +#include "AXObjectCache.h" +#include "BlockExceptions.h" +#include "Chrome.h" +#include "ChromeClient.h" +#include "ClipboardMac.h" +#include "DragController.h" +#include "EventNames.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameView.h" +#include "KeyboardEvent.h" +#include "MouseEventWithHitTestResults.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "RenderWidget.h" +#include "RuntimeApplicationChecks.h" +#include "Scrollbar.h" +#include "Settings.h" +#include "WebCoreSystemInterface.h" +#include <objc/objc-runtime.h> +#include <wtf/StdLibExtras.h> + +#if !(defined(OBJC_API_VERSION) && OBJC_API_VERSION > 0) +static inline IMP method_setImplementation(Method m, IMP i) +{ + IMP oi = m->method_imp; + m->method_imp = i; + return oi; +} +#endif + +namespace WebCore { + +#if ENABLE(DRAG_SUPPORT) +const double EventHandler::TextDragDelay = 0.15; +#endif + +static RetainPtr<NSEvent>& currentNSEventSlot() +{ + DEFINE_STATIC_LOCAL(RetainPtr<NSEvent>, event, ()); + return event; +} + +NSEvent *EventHandler::currentNSEvent() +{ + return currentNSEventSlot().get(); +} + +class CurrentEventScope : public Noncopyable { +public: + CurrentEventScope(NSEvent *); + ~CurrentEventScope(); + +private: + RetainPtr<NSEvent> m_savedCurrentEvent; +#ifndef NDEBUG + RetainPtr<NSEvent> m_event; +#endif +}; + +inline CurrentEventScope::CurrentEventScope(NSEvent *event) + : m_savedCurrentEvent(currentNSEventSlot()) +#ifndef NDEBUG + , m_event(event) +#endif +{ + currentNSEventSlot() = event; +} + +inline CurrentEventScope::~CurrentEventScope() +{ + ASSERT(currentNSEventSlot() == m_event); + currentNSEventSlot() = m_savedCurrentEvent; +} + +bool EventHandler::wheelEvent(NSEvent *event) +{ + Page* page = m_frame->page(); + if (!page) + return false; + + CurrentEventScope scope(event); + + m_useLatchedWheelEventNode = wkIsLatchingWheelEvent(event); + + PlatformWheelEvent wheelEvent(event, page->chrome()->platformPageClient()); + handleWheelEvent(wheelEvent); + + return wheelEvent.isAccepted(); +} + +PassRefPtr<KeyboardEvent> EventHandler::currentKeyboardEvent() const +{ + NSEvent *event = [NSApp currentEvent]; + if (!event) + return 0; + switch ([event type]) { + case NSKeyDown: { + PlatformKeyboardEvent platformEvent(event); + platformEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown); + return KeyboardEvent::create(platformEvent, m_frame->document()->defaultView()); + } + case NSKeyUp: + return KeyboardEvent::create(event, m_frame->document()->defaultView()); + default: + return 0; + } +} + +bool EventHandler::keyEvent(NSEvent *event) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + ASSERT([event type] == NSKeyDown || [event type] == NSKeyUp); + + CurrentEventScope scope(event); + return keyEvent(PlatformKeyboardEvent(event)); + + END_BLOCK_OBJC_EXCEPTIONS; + + return false; +} + +void EventHandler::focusDocumentView() +{ + Page* page = m_frame->page(); + if (!page) + return; + + if (FrameView* frameView = m_frame->view()) { + if (NSView *documentView = frameView->documentView()) + page->chrome()->focusNSView(documentView); + } + + page->focusController()->setFocusedFrame(m_frame); +} + +bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event) +{ + // Figure out which view to send the event to. + RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0; + if (!target || !target->isWidget()) + return false; + + // Double-click events don't exist in Cocoa. Since passWidgetMouseDownEventToWidget will + // just pass currentEvent down to the widget, we don't want to call it for events that + // don't correspond to Cocoa events. The mousedown/ups will have already been passed on as + // part of the pressed/released handling. + return passMouseDownEventToWidget(toRenderWidget(target)->widget()); +} + +bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) +{ + return passMouseDownEventToWidget(renderWidget->widget()); +} + +static bool lastEventIsMouseUp() +{ + // Many AppKit widgets run their own event loops and consume events while the mouse is down. + // When they finish, currentEvent is the mouseUp that they exited on. We need to update + // the WebCore state with this mouseUp, which we never saw. This method lets us detect + // that state. Handling this was critical when we used AppKit widgets for form elements. + // It's not clear in what cases this is helpful now -- it's possible it can be removed. + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + NSEvent *currentEventAfterHandlingMouseDown = [NSApp currentEvent]; + return EventHandler::currentNSEvent() != currentEventAfterHandlingMouseDown + && [currentEventAfterHandlingMouseDown type] == NSLeftMouseUp + && [currentEventAfterHandlingMouseDown timestamp] >= [EventHandler::currentNSEvent() timestamp]; + END_BLOCK_OBJC_EXCEPTIONS; + + return false; +} + +bool EventHandler::passMouseDownEventToWidget(Widget* pWidget) +{ + // FIXME: This function always returns true. It should be changed either to return + // false in some cases or the return value should be removed. + + RefPtr<Widget> widget = pWidget; + + if (!widget) { + LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed"); + return true; + } + + // In WebKit2 we will never have an NSView. Just return early and let the regular event handler machinery take care of + // dispatching the event. + if (!widget->platformWidget()) + return false; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSView *nodeView = widget->platformWidget(); + ASSERT([nodeView superview]); + NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]]; + if (!view) { + // We probably hit the border of a RenderWidget + return true; + } + + Page* page = m_frame->page(); + if (!page) + return true; + + if (page->chrome()->client()->firstResponder() != view) { + // Normally [NSWindow sendEvent:] handles setting the first responder. + // But in our case, the event was sent to the view representing the entire web page. + if ([currentNSEvent() clickCount] <= 1 && [view acceptsFirstResponder] && [view needsPanelToBecomeKey]) + page->chrome()->client()->makeFirstResponder(view); + } + + // We need to "defer loading" while tracking the mouse, because tearing down the + // page while an AppKit control is tracking the mouse can cause a crash. + + // FIXME: In theory, WebCore now tolerates tear-down while tracking the + // mouse. We should confirm that, and then remove the deferrsLoading + // hack entirely. + + bool wasDeferringLoading = page->defersLoading(); + if (!wasDeferringLoading) + page->setDefersLoading(true); + + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + NSView *outerView = widget->getOuterView(); + widget->beforeMouseDown(outerView, widget.get()); + [view mouseDown:currentNSEvent()]; + widget->afterMouseDown(outerView, widget.get()); + m_sendingEventToSubview = false; + + if (!wasDeferringLoading) + page->setDefersLoading(false); + + // Remember which view we sent the event to, so we can direct the release event properly. + m_mouseDownView = view; + m_mouseDownWasInSubframe = false; + + // Many AppKit widgets run their own event loops and consume events while the mouse is down. + // When they finish, currentEvent is the mouseUp that they exited on. We need to update + // the EventHandler state with this mouseUp, which we never saw. + // If this event isn't a mouseUp, we assume that the mouseUp will be coming later. There + // is a hole here if the widget consumes both the mouseUp and subsequent events. + if (lastEventIsMouseUp()) + m_mousePressed = false; + + END_BLOCK_OBJC_EXCEPTIONS; + + return true; +} + +// Note that this does the same kind of check as [target isDescendantOf:superview]. +// There are two differences: This is a lot slower because it has to walk the whole +// tree, and this works in cases where the target has already been deallocated. +static bool findViewInSubviews(NSView *superview, NSView *target) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + NSEnumerator *e = [[superview subviews] objectEnumerator]; + NSView *subview; + while ((subview = [e nextObject])) { + if (subview == target || findViewInSubviews(subview, target)) { + return true; + } + } + END_BLOCK_OBJC_EXCEPTIONS; + + return false; +} + +NSView *EventHandler::mouseDownViewIfStillGood() +{ + // Since we have no way of tracking the lifetime of m_mouseDownView, we have to assume that + // it could be deallocated already. We search for it in our subview tree; if we don't find + // it, we set it to nil. + NSView *mouseDownView = m_mouseDownView; + if (!mouseDownView) { + return nil; + } + FrameView* topFrameView = m_frame->view(); + NSView *topView = topFrameView ? topFrameView->platformWidget() : nil; + if (!topView || !findViewInSubviews(topView, mouseDownView)) { + m_mouseDownView = nil; + return nil; + } + return mouseDownView; +} + +#if ENABLE(DRAG_SUPPORT) +bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&) +{ + NSView *view = mouseDownViewIfStillGood(); + + if (!view) + return false; + + if (!m_mouseDownWasInSubframe) { + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [view mouseDragged:currentNSEvent()]; + END_BLOCK_OBJC_EXCEPTIONS; + m_sendingEventToSubview = false; + } + + return true; +} +#endif // ENABLE(DRAG_SUPPORT) + +bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) +{ + NSView *view = mouseDownViewIfStillGood(); + if (!view) + return false; + + if (!m_mouseDownWasInSubframe) { + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [view mouseUp:currentNSEvent()]; + END_BLOCK_OBJC_EXCEPTIONS; + m_sendingEventToSubview = false; + } + + return true; +} + +bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& event, Frame* subframe, HitTestResult* hoveredNode) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + switch ([currentNSEvent() type]) { + case NSLeftMouseDragged: + case NSOtherMouseDragged: + case NSRightMouseDragged: + // This check is bogus and results in <rdar://6813830>, but removing it breaks a number of + // layout tests. + if (!m_mouseDownWasInSubframe) + return false; +#if ENABLE(DRAG_SUPPORT) + if (subframe->page()->dragController()->didInitiateDrag()) + return false; +#endif + case NSMouseMoved: + // Since we're passing in currentNSEvent() here, we can call + // handleMouseMoveEvent() directly, since the save/restore of + // currentNSEvent() that mouseMoved() does would have no effect. + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + subframe->eventHandler()->handleMouseMoveEvent(currentPlatformMouseEvent(), hoveredNode); + m_sendingEventToSubview = false; + return true; + + case NSLeftMouseDown: { + Node* node = event.targetNode(); + if (!node) + return false; + RenderObject* renderer = node->renderer(); + if (!renderer || !renderer->isWidget()) + return false; + Widget* widget = toRenderWidget(renderer)->widget(); + if (!widget || !widget->isFrameView()) + return false; + if (!passWidgetMouseDownEventToWidget(toRenderWidget(renderer))) + return false; + m_mouseDownWasInSubframe = true; + return true; + } + case NSLeftMouseUp: { + if (!m_mouseDownWasInSubframe) + return false; + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + subframe->eventHandler()->handleMouseReleaseEvent(currentPlatformMouseEvent()); + m_sendingEventToSubview = false; + return true; + } + default: + return false; + } + END_BLOCK_OBJC_EXCEPTIONS; + + return false; +} + +static IMP originalNSScrollViewScrollWheel; +static bool _nsScrollViewScrollWheelShouldRetainSelf; +static void selfRetainingNSScrollViewScrollWheel(NSScrollView *, SEL, NSEvent *); + +static bool nsScrollViewScrollWheelShouldRetainSelf() +{ + ASSERT(isMainThread()); + + return _nsScrollViewScrollWheelShouldRetainSelf; +} + +static void setNSScrollViewScrollWheelShouldRetainSelf(bool shouldRetain) +{ + ASSERT(isMainThread()); + + if (!originalNSScrollViewScrollWheel) { + Method method = class_getInstanceMethod(objc_getRequiredClass("NSScrollView"), @selector(scrollWheel:)); + originalNSScrollViewScrollWheel = method_setImplementation(method, reinterpret_cast<IMP>(selfRetainingNSScrollViewScrollWheel)); + } + + _nsScrollViewScrollWheelShouldRetainSelf = shouldRetain; +} + +static void selfRetainingNSScrollViewScrollWheel(NSScrollView *self, SEL selector, NSEvent *event) +{ + bool shouldRetainSelf = isMainThread() && nsScrollViewScrollWheelShouldRetainSelf(); + + if (shouldRetainSelf) + [self retain]; + originalNSScrollViewScrollWheel(self, selector, event); + if (shouldRetainSelf) + [self release]; +} + +bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& wheelEvent, Widget* widget) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + if (!widget) + return false; + + NSView* nodeView = widget->platformWidget(); + if (!nodeView) { + // WebKit2 code path. + if (!widget->isFrameView()) + return false; + + return static_cast<FrameView*>(widget)->frame()->eventHandler()->handleWheelEvent(wheelEvent); + } + + if ([currentNSEvent() type] != NSScrollWheel || m_sendingEventToSubview) + return false; + + ASSERT(nodeView); + ASSERT([nodeView superview]); + NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]]; + if (!view) + // We probably hit the border of a RenderWidget + return false; + + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + // Work around <rdar://problem/6806810> which can cause -[NSScrollView scrollWheel:] to + // crash if the NSScrollView is released during timer or network callback dispatch + // in the nested tracking runloop that -[NSScrollView scrollWheel:] runs. + setNSScrollViewScrollWheelShouldRetainSelf(true); + [view scrollWheel:currentNSEvent()]; + setNSScrollViewScrollWheelShouldRetainSelf(false); + m_sendingEventToSubview = false; + return true; + + END_BLOCK_OBJC_EXCEPTIONS; + return false; +} + +void EventHandler::mouseDown(NSEvent *event) +{ + FrameView* v = m_frame->view(); + if (!v || m_sendingEventToSubview) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + m_frame->loader()->resetMultipleFormSubmissionProtection(); + + m_mouseDownView = nil; + + CurrentEventScope scope(event); + + handleMousePressEvent(currentPlatformMouseEvent()); + + END_BLOCK_OBJC_EXCEPTIONS; +} + +void EventHandler::mouseDragged(NSEvent *event) +{ + FrameView* v = m_frame->view(); + if (!v || m_sendingEventToSubview) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + CurrentEventScope scope(event); + handleMouseMoveEvent(currentPlatformMouseEvent()); + + END_BLOCK_OBJC_EXCEPTIONS; +} + +void EventHandler::mouseUp(NSEvent *event) +{ + FrameView* v = m_frame->view(); + if (!v || m_sendingEventToSubview) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + CurrentEventScope scope(event); + + // Our behavior here is a little different that Qt. Qt always sends + // a mouse release event, even for a double click. To correct problems + // in khtml's DOM click event handling we do not send a release here + // for a double click. Instead we send that event from FrameView's + // handleMouseDoubleClickEvent. Note also that the third click of + // a triple click is treated as a single click, but the fourth is then + // treated as another double click. Hence the "% 2" below. + int clickCount = [event clickCount]; + if (clickCount > 0 && clickCount % 2 == 0) + handleMouseDoubleClickEvent(currentPlatformMouseEvent()); + else + handleMouseReleaseEvent(currentPlatformMouseEvent()); + + m_mouseDownView = nil; + + END_BLOCK_OBJC_EXCEPTIONS; +} + +/* + A hack for the benefit of AK's PopUpButton, which uses the Carbon menu manager, which thus + eats all subsequent events after it is starts its modal tracking loop. After the interaction + is done, this routine is used to fix things up. When a mouse down started us tracking in + the widget, we post a fake mouse up to balance the mouse down we started with. When a + key down started us tracking in the widget, we post a fake key up to balance things out. + In addition, we post a fake mouseMoved to get the cursor in sync with whatever we happen to + be over after the tracking is done. + */ +void EventHandler::sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent) +{ + FrameView* view = m_frame->view(); + if (!view) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + m_sendingEventToSubview = false; + int eventType = [initiatingEvent type]; + if (eventType == NSLeftMouseDown || eventType == NSKeyDown) { + NSEvent *fakeEvent = nil; + if (eventType == NSLeftMouseDown) { + fakeEvent = [NSEvent mouseEventWithType:NSLeftMouseUp + location:[initiatingEvent locationInWindow] + modifierFlags:[initiatingEvent modifierFlags] + timestamp:[initiatingEvent timestamp] + windowNumber:[initiatingEvent windowNumber] + context:[initiatingEvent context] + eventNumber:[initiatingEvent eventNumber] + clickCount:[initiatingEvent clickCount] + pressure:[initiatingEvent pressure]]; + + [NSApp postEvent:fakeEvent atStart:YES]; + } else { // eventType == NSKeyDown + fakeEvent = [NSEvent keyEventWithType:NSKeyUp + location:[initiatingEvent locationInWindow] + modifierFlags:[initiatingEvent modifierFlags] + timestamp:[initiatingEvent timestamp] + windowNumber:[initiatingEvent windowNumber] + context:[initiatingEvent context] + characters:[initiatingEvent characters] + charactersIgnoringModifiers:[initiatingEvent charactersIgnoringModifiers] + isARepeat:[initiatingEvent isARepeat] + keyCode:[initiatingEvent keyCode]]; + [NSApp postEvent:fakeEvent atStart:YES]; + } + // FIXME: We should really get the current modifierFlags here, but there's no way to poll + // them in Cocoa, and because the event stream was stolen by the Carbon menu code we have + // no up-to-date cache of them anywhere. + fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved + location:[[view->platformWidget() window] convertScreenToBase:[NSEvent mouseLocation]] + modifierFlags:[initiatingEvent modifierFlags] + timestamp:[initiatingEvent timestamp] + windowNumber:[initiatingEvent windowNumber] + context:[initiatingEvent context] + eventNumber:0 + clickCount:0 + pressure:0]; + [NSApp postEvent:fakeEvent atStart:YES]; + } + + END_BLOCK_OBJC_EXCEPTIONS; +} + +void EventHandler::mouseMoved(NSEvent *event) +{ + // Reject a mouse moved if the button is down - screws up tracking during autoscroll + // These happen because WebKit sometimes has to fake up moved events. + if (!m_frame->view() || m_mousePressed || m_sendingEventToSubview) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + CurrentEventScope scope(event); + mouseMoved(currentPlatformMouseEvent()); + END_BLOCK_OBJC_EXCEPTIONS; +} + +static bool frameHasPlatformWidget(Frame* frame) +{ + if (FrameView* frameView = frame->view()) { + if (frameView->platformWidget()) + return true; + } + + return false; +} + +bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) +{ + // WebKit1 code path. + if (frameHasPlatformWidget(m_frame)) + return passSubframeEventToSubframe(mev, subframe); + + // WebKit2 code path. + subframe->eventHandler()->handleMousePressEvent(mev.event()); + return true; +} + +bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode) +{ + // WebKit1 code path. + if (frameHasPlatformWidget(m_frame)) + return passSubframeEventToSubframe(mev, subframe, hoveredNode); + + // WebKit2 code path. + if (m_mouseDownMayStartDrag && !m_mouseDownWasInSubframe) + return false; + subframe->eventHandler()->handleMouseMoveEvent(mev.event(), hoveredNode); + return true; +} + +bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) +{ + // WebKit1 code path. + if (frameHasPlatformWidget(m_frame)) + return passSubframeEventToSubframe(mev, subframe); + + // WebKit2 code path. + subframe->eventHandler()->handleMouseReleaseEvent(mev.event()); + return true; +} + +PlatformMouseEvent EventHandler::currentPlatformMouseEvent() const +{ + NSView *windowView = nil; + if (Page* page = m_frame->page()) + windowView = page->chrome()->platformPageClient(); + return PlatformMouseEvent(currentNSEvent(), windowView); +} + +#if ENABLE(CONTEXT_MENUS) +bool EventHandler::sendContextMenuEvent(NSEvent *event) +{ + Page* page = m_frame->page(); + if (!page) + return false; + return sendContextMenuEvent(PlatformMouseEvent(event, page->chrome()->platformPageClient())); +} +#endif // ENABLE(CONTEXT_MENUS) + +#if ENABLE(DRAG_SUPPORT) +bool EventHandler::eventMayStartDrag(NSEvent *event) +{ + Page* page = m_frame->page(); + if (!page) + return false; + return eventMayStartDrag(PlatformMouseEvent(event, page->chrome()->platformPageClient())); +} +#endif // ENABLE(DRAG_SUPPORT) + +bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const +{ + return m_activationEventNumber == event.eventNumber(); +} + +#if ENABLE(DRAG_SUPPORT) + +PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const +{ + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + // Must be done before ondragstart adds types and data to the pboard, + // also done for security, as it erases data from the last drag + [pasteboard declareTypes:[NSArray array] owner:nil]; + return ClipboardMac::create(Clipboard::DragAndDrop, pasteboard, ClipboardWritable, m_frame); +} + +#endif + +static inline bool isKeyboardOptionTab(KeyboardEvent* event) +{ + return event + && (event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent) + && event->altKey() + && event->keyIdentifier() == "U+0009"; +} + +bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent* event) const +{ + return isKeyboardOptionTab(event); +} + +bool EventHandler::tabsToAllControls(KeyboardEvent* event) const +{ + Page* page = m_frame->page(); + if (!page) + return false; + + KeyboardUIMode keyboardUIMode = page->chrome()->client()->keyboardUIMode(); + bool handlingOptionTab = isKeyboardOptionTab(event); + + // If tab-to-links is off, option-tab always highlights all controls + if ((keyboardUIMode & KeyboardAccessTabsToLinks) == 0 && handlingOptionTab) + return true; + + // If system preferences say to include all controls, we always include all controls + if (keyboardUIMode & KeyboardAccessFull) + return true; + + // Otherwise tab-to-links includes all controls, unless the sense is flipped via option-tab. + if (keyboardUIMode & KeyboardAccessTabsToLinks) + return !handlingOptionTab; + + return handlingOptionTab; +} + +bool EventHandler::needsKeyboardEventDisambiguationQuirks() const +{ + Document* document = m_frame->document(); + + // RSS view needs arrow key keypress events. + if (applicationIsSafari() && (document->url().protocolIs("feed") || document->url().protocolIs("feeds"))) + return true; + Settings* settings = m_frame->settings(); + if (!settings) + return false; + +#if ENABLE(DASHBOARD_SUPPORT) + if (settings->usesDashboardBackwardCompatibilityMode()) + return true; +#endif + + if (settings->needsKeyboardEventDisambiguationQuirks()) + return true; + + return false; +} + +unsigned EventHandler::accessKeyModifiers() +{ + // Control+Option key combinations are usually unused on Mac OS X, but not when VoiceOver is enabled. + // So, we use Control in this case, even though it conflicts with Emacs-style key bindings. + // See <https://bugs.webkit.org/show_bug.cgi?id=21107> for more detail. + if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled()) + return PlatformKeyboardEvent::CtrlKey; + + return PlatformKeyboardEvent::CtrlKey | PlatformKeyboardEvent::AltKey; +} + +} diff --git a/Source/WebCore/page/mac/FrameMac.mm b/Source/WebCore/page/mac/FrameMac.mm new file mode 100644 index 0000000..d4e4098 --- /dev/null +++ b/Source/WebCore/page/mac/FrameMac.mm @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "Frame.h" + +#import "BlockExceptions.h" +#import "ColorMac.h" +#import "Cursor.h" +#import "DOMInternal.h" +#import "Event.h" +#import "FrameLoaderClient.h" +#import "FrameView.h" +#import "GraphicsContext.h" +#import "HTMLNames.h" +#import "HTMLTableCellElement.h" +#import "HitTestRequest.h" +#import "HitTestResult.h" +#import "KeyboardEvent.h" +#import "Logging.h" +#import "MouseEventWithHitTestResults.h" +#import "Page.h" +#import "PlatformKeyboardEvent.h" +#import "PlatformWheelEvent.h" +#import "RegularExpression.h" +#import "RenderTableCell.h" +#import "Scrollbar.h" +#import "SimpleFontData.h" +#import "WebCoreViewFactory.h" +#import "visible_units.h" +#import <Carbon/Carbon.h> +#import <wtf/StdLibExtras.h> + +@interface NSView (WebCoreHTMLDocumentView) +- (void)drawSingleRect:(NSRect)rect; +@end + +using namespace std; + +namespace WebCore { + +using namespace HTMLNames; + +// Either get cached regexp or build one that matches any of the labels. +// The regexp we build is of the form: (STR1|STR2|STRN) +static RegularExpression* regExpForLabels(NSArray* labels) +{ + // All the ObjC calls in this method are simple array and string + // calls which we can assume do not raise exceptions + + + // Parallel arrays that we use to cache regExps. In practice the number of expressions + // that the app will use is equal to the number of locales is used in searching. + static const unsigned int regExpCacheSize = 4; + static NSMutableArray* regExpLabels = nil; + DEFINE_STATIC_LOCAL(Vector<RegularExpression*>, regExps, ()); + DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive)); + + RegularExpression* result; + if (!regExpLabels) + regExpLabels = [[NSMutableArray alloc] initWithCapacity:regExpCacheSize]; + CFIndex cacheHit = [regExpLabels indexOfObject:labels]; + if (cacheHit != NSNotFound) + result = regExps.at(cacheHit); + else { + String pattern("("); + unsigned int numLabels = [labels count]; + unsigned int i; + for (i = 0; i < numLabels; i++) { + String label = [labels objectAtIndex:i]; + + bool startsWithWordChar = false; + bool endsWithWordChar = false; + if (label.length() != 0) { + startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0; + endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0; + } + + if (i != 0) + pattern.append("|"); + // Search for word boundaries only if label starts/ends with "word characters". + // If we always searched for word boundaries, this wouldn't work for languages + // such as Japanese. + if (startsWithWordChar) + pattern.append("\\b"); + pattern.append(label); + if (endsWithWordChar) + pattern.append("\\b"); + } + pattern.append(")"); + result = new RegularExpression(pattern, TextCaseInsensitive); + } + + // add regexp to the cache, making sure it is at the front for LRU ordering + if (cacheHit != 0) { + if (cacheHit != NSNotFound) { + // remove from old spot + [regExpLabels removeObjectAtIndex:cacheHit]; + regExps.remove(cacheHit); + } + // add to start + [regExpLabels insertObject:labels atIndex:0]; + regExps.insert(0, result); + // trim if too big + if ([regExpLabels count] > regExpCacheSize) { + [regExpLabels removeObjectAtIndex:regExpCacheSize]; + RegularExpression* last = regExps.last(); + regExps.removeLast(); + delete last; + } + } + return result; +} + +NSString* Frame::searchForLabelsBeforeElement(NSArray* labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove) +{ + RegularExpression* regExp = regExpForLabels(labels); + // We stop searching after we've seen this many chars + const unsigned int charsSearchedThreshold = 500; + // This is the absolute max we search. We allow a little more slop than + // charsSearchedThreshold, to make it more likely that we'll search whole nodes. + const unsigned int maxCharsSearched = 600; + // If the starting element is within a table, the cell that contains it + HTMLTableCellElement* startingTableCell = 0; + bool searchedCellAbove = false; + + if (resultDistance) + *resultDistance = notFound; + if (resultIsInCellAbove) + *resultIsInCellAbove = false; + + // walk backwards in the node tree, until another element, or form, or end of tree + unsigned lengthSearched = 0; + Node* n; + for (n = element->traversePreviousNode(); + n && lengthSearched < charsSearchedThreshold; + n = n->traversePreviousNode()) + { + if (n->hasTagName(formTag) + || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())) + { + // We hit another form element or the start of the form - bail out + break; + } else if (n->hasTagName(tdTag) && !startingTableCell) { + startingTableCell = static_cast<HTMLTableCellElement*>(n); + } else if (n->hasTagName(trTag) && startingTableCell) { + NSString* result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance); + if (result && [result length] > 0) { + if (resultIsInCellAbove) + *resultIsInCellAbove = true; + return result; + } + searchedCellAbove = true; + } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { + // For each text chunk, run the regexp + String nodeString = n->nodeValue(); + // add 100 for slop, to make it more likely that we'll search whole nodes + if (lengthSearched + nodeString.length() > maxCharsSearched) + nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); + int pos = regExp->searchRev(nodeString); + if (pos >= 0) { + if (resultDistance) + *resultDistance = lengthSearched; + return nodeString.substring(pos, regExp->matchedLength()); + } + lengthSearched += nodeString.length(); + } + } + + // If we started in a cell, but bailed because we found the start of the form or the + // previous element, we still might need to search the row above us for a label. + if (startingTableCell && !searchedCellAbove) { + NSString* result = searchForLabelsAboveCell(regExp, startingTableCell, resultDistance); + if (result && [result length] > 0) { + if (resultIsInCellAbove) + *resultIsInCellAbove = true; + return result; + } + } + + return nil; +} + +static NSString *matchLabelsAgainstString(NSArray *labels, const String& stringToMatch) +{ + if (stringToMatch.isEmpty()) + return nil; + + String mutableStringToMatch = stringToMatch; + + // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" + replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " "); + mutableStringToMatch.replace('_', ' '); + + RegularExpression* regExp = regExpForLabels(labels); + // Use the largest match we can find in the whole string + int pos; + int length; + int bestPos = -1; + int bestLength = -1; + int start = 0; + do { + pos = regExp->match(mutableStringToMatch, start); + if (pos != -1) { + length = regExp->matchedLength(); + if (length >= bestLength) { + bestPos = pos; + bestLength = length; + } + start = pos + 1; + } + } while (pos != -1); + + if (bestPos != -1) + return mutableStringToMatch.substring(bestPos, bestLength); + return nil; +} + +NSString* Frame::matchLabelsAgainstElement(NSArray* labels, Element* element) +{ + // Match against the name element, then against the id element if no match is found for the name element. + // See 7538330 for one popular site that benefits from the id element check. + // FIXME: This code is mirrored in Frame.cpp. It would be nice to make the Mac code call the platform-agnostic + // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way. + String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getAttribute(nameAttr)); + if (!resultFromNameAttribute.isEmpty()) + return resultFromNameAttribute; + + return matchLabelsAgainstString(labels, element->getAttribute(idAttr)); +} + +NSImage* Frame::imageFromRect(NSRect rect) const +{ + NSView* view = m_view->documentView(); + if (!view) + return nil; + if (![view respondsToSelector:@selector(drawSingleRect:)]) + return nil; + + PaintBehavior oldPaintBehavior = m_view->paintBehavior(); + m_view->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers); + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSRect bounds = [view bounds]; + + // Round image rect size in window coordinate space to avoid pixel cracks at HiDPI (4622794) + rect = [view convertRect:rect toView:nil]; + rect.size.height = roundf(rect.size.height); + rect.size.width = roundf(rect.size.width); + rect = [view convertRect:rect fromView:nil]; + + NSImage* resultImage = [[[NSImage alloc] initWithSize:rect.size] autorelease]; + + if (rect.size.width != 0 && rect.size.height != 0) { + [resultImage setFlipped:YES]; + [resultImage lockFocus]; + CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(context); + CGContextTranslateCTM(context, bounds.origin.x - rect.origin.x, bounds.origin.y - rect.origin.y); + + // Note: Must not call drawRect: here, because drawRect: assumes that it's called from AppKit's + // display machinery. It calls getRectsBeingDrawn:count:, which can only be called inside + // when a real AppKit display is underway. + [view drawSingleRect:rect]; + + CGContextRestoreGState(context); + [resultImage unlockFocus]; + [resultImage setFlipped:NO]; + } + + m_view->setPaintBehavior(oldPaintBehavior); + return resultImage; + + END_BLOCK_OBJC_EXCEPTIONS; + + m_view->setPaintBehavior(oldPaintBehavior); + return nil; +} + +NSImage* Frame::selectionImage(bool forceBlackText) const +{ + m_view->setPaintBehavior(PaintBehaviorSelectionOnly | (forceBlackText ? PaintBehaviorForceBlackText : 0)); + m_doc->updateLayout(); + NSImage* result = imageFromRect(selection()->bounds()); + m_view->setPaintBehavior(PaintBehaviorNormal); + return result; +} + +NSImage* Frame::snapshotDragImage(Node* node, NSRect* imageRect, NSRect* elementRect) const +{ + RenderObject* renderer = node->renderer(); + if (!renderer) + return nil; + + renderer->updateDragState(true); // mark dragged nodes (so they pick up the right CSS) + m_doc->updateLayout(); // forces style recalc - needed since changing the drag state might + // imply new styles, plus JS could have changed other things + IntRect topLevelRect; + NSRect paintingRect = renderer->paintingRootRect(topLevelRect); + + m_view->setNodeToDraw(node); // invoke special sub-tree drawing mode + NSImage* result = imageFromRect(paintingRect); + renderer->updateDragState(false); + m_doc->updateLayout(); + m_view->setNodeToDraw(0); + + if (elementRect) + *elementRect = topLevelRect; + if (imageRect) + *imageRect = paintingRect; + return result; +} + +DragImageRef Frame::nodeImage(Node* node) +{ + RenderObject* renderer = node->renderer(); + if (!renderer) + return nil; + + m_doc->updateLayout(); // forces style recalc + + IntRect topLevelRect; + NSRect paintingRect = renderer->paintingRootRect(topLevelRect); + + m_view->setNodeToDraw(node); // invoke special sub-tree drawing mode + NSImage* result = imageFromRect(paintingRect); + m_view->setNodeToDraw(0); + + return result; +} + +DragImageRef Frame::dragImageForSelection() +{ + if (!selection()->isRange()) + return nil; + return selectionImage(); +} + +} // namespace WebCore diff --git a/Source/WebCore/page/mac/PageMac.cpp b/Source/WebCore/page/mac/PageMac.cpp new file mode 100644 index 0000000..7386eea --- /dev/null +++ b/Source/WebCore/page/mac/PageMac.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "DocumentLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "Page.h" + +namespace WebCore { + +void Page::addSchedulePair(PassRefPtr<SchedulePair> prpPair) +{ + RefPtr<SchedulePair> pair = prpPair; + + if (!m_scheduledRunLoopPairs) + m_scheduledRunLoopPairs.set(new SchedulePairHashSet); + m_scheduledRunLoopPairs->add(pair); + +#ifndef BUILDING_ON_TIGER + for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) { + if (DocumentLoader* documentLoader = frame->loader()->documentLoader()) + documentLoader->schedule(pair.get()); + if (DocumentLoader* documentLoader = frame->loader()->provisionalDocumentLoader()) + documentLoader->schedule(pair.get()); + } +#endif + + // FIXME: make SharedTimerMac use these SchedulePairs. +} + +void Page::removeSchedulePair(PassRefPtr<SchedulePair> prpPair) +{ + ASSERT(m_scheduledRunLoopPairs); + if (!m_scheduledRunLoopPairs) + return; + + RefPtr<SchedulePair> pair = prpPair; + m_scheduledRunLoopPairs->remove(pair); + +#ifndef BUILDING_ON_TIGER + for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) { + if (DocumentLoader* documentLoader = frame->loader()->documentLoader()) + documentLoader->unschedule(pair.get()); + if (DocumentLoader* documentLoader = frame->loader()->provisionalDocumentLoader()) + documentLoader->unschedule(pair.get()); + } +#endif +} + +} // namespace diff --git a/Source/WebCore/page/mac/WebCoreFrameView.h b/Source/WebCore/page/mac/WebCoreFrameView.h new file mode 100644 index 0000000..b76350d --- /dev/null +++ b/Source/WebCore/page/mac/WebCoreFrameView.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2003, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ScrollTypes.h" + +namespace WebCore { + class Frame; +} + +@protocol WebCoreFrameScrollView +- (void)setScrollingModes:(WebCore::ScrollbarMode)hMode vertical:(WebCore::ScrollbarMode)vMode andLock:(BOOL)lock; +- (void)scrollingModes:(WebCore::ScrollbarMode*)hMode vertical:(WebCore::ScrollbarMode*)vMode; +- (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint; +- (void)setScrollOrigin:(NSPoint)origin updatePosition:(BOOL)updatePosition; +- (NSPoint)scrollOrigin; +@end + +@protocol WebCoreFrameView +- (WebCore::Frame*)_web_frame; +@end diff --git a/Source/WebCore/page/mac/WebCoreKeyboardUIMode.h b/Source/WebCore/page/mac/WebCoreKeyboardUIMode.h new file mode 100644 index 0000000..187cf09 --- /dev/null +++ b/Source/WebCore/page/mac/WebCoreKeyboardUIMode.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 WebCoreKeyboardUIMode_h +#define WebCoreKeyboardUIMode_h + +namespace WebCore { + + enum KeyboardUIMode { + KeyboardAccessDefault = 0x00000000, + KeyboardAccessFull = 0x00000001, + // this flag may be or'ed with either of the two above + KeyboardAccessTabsToLinks = 0x10000000 + }; + +} + +#endif diff --git a/Source/WebCore/page/mac/WebCoreViewFactory.h b/Source/WebCore/page/mac/WebCoreViewFactory.h new file mode 100644 index 0000000..7af75cb --- /dev/null +++ b/Source/WebCore/page/mac/WebCoreViewFactory.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2003, 2005, 2009, 2010 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +@class WebCoreTextMarker; +@class WebCoreTextMarkerRange; + +@protocol WebCoreViewFactory + +- (BOOL)objectIsTextMarker:(id)object; +- (BOOL)objectIsTextMarkerRange:(id)object; + +- (WebCoreTextMarker *)textMarkerWithBytes:(const void *)bytes length:(size_t)length; +- (BOOL)getBytes:(void *)bytes fromTextMarker:(WebCoreTextMarker *)textMarker length:(size_t)length; + +- (WebCoreTextMarkerRange *)textMarkerRangeWithStart:(WebCoreTextMarker *)start end:(WebCoreTextMarker *)end; +- (WebCoreTextMarker *)startOfTextMarkerRange:(WebCoreTextMarkerRange *)range; +- (WebCoreTextMarker *)endOfTextMarkerRange:(WebCoreTextMarkerRange *)range; + +- (void)accessibilityHandleFocusChanged; +- (CGRect)accessibilityConvertScreenRect:(CGRect)bounds; + +- (AXUIElementRef)AXUIElementForElement:(id)element; +- (void)unregisterUniqueIdForUIElement:(id)element; + +@end + +@interface WebCoreViewFactory : NSObject ++ (WebCoreViewFactory *)sharedFactory; +@end + +@interface WebCoreViewFactory (SubclassResponsibility) <WebCoreViewFactory> +@end diff --git a/Source/WebCore/page/mac/WebCoreViewFactory.m b/Source/WebCore/page/mac/WebCoreViewFactory.m new file mode 100644 index 0000000..5398989 --- /dev/null +++ b/Source/WebCore/page/mac/WebCoreViewFactory.m @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2003 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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" +#import "WebCoreViewFactory.h" +#import <wtf/Assertions.h> + +@implementation WebCoreViewFactory + +static WebCoreViewFactory *sharedFactory; + ++ (WebCoreViewFactory *)sharedFactory +{ + return sharedFactory; +} + +- init +{ + [super init]; + + ASSERT(!sharedFactory); + sharedFactory = [self retain]; + + return self; +} + +@end |