diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/mac')
-rw-r--r-- | Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm | 451 |
1 files changed, 296 insertions, 155 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm index 8d81889..d7b352c 100644 --- a/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm +++ b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm @@ -27,10 +27,13 @@ #import "WebPage.h" #import "AccessibilityWebPageObject.h" +#import "AttributedString.h" #import "DataReference.h" +#import "EditorState.h" #import "PluginView.h" #import "WebCoreArgumentCoders.h" #import "WebEvent.h" +#import "WebEventConversion.h" #import "WebFrame.h" #import "WebPageProxyMessages.h" #import "WebProcess.h" @@ -39,6 +42,7 @@ #import <WebCore/Frame.h> #import <WebCore/FrameView.h> #import <WebCore/HitTestResult.h> +#import <WebCore/HTMLConverter.h> #import <WebCore/KeyboardEvent.h> #import <WebCore/Page.h> #import <WebCore/PlatformKeyboardEvent.h> @@ -53,6 +57,8 @@ using namespace WebCore; namespace WebKit { +static PassRefPtr<Range> convertToRange(Frame*, NSRange); + void WebPage::platformInitialize() { m_page->addSchedulePair(SchedulePair::create([NSRunLoop currentRunLoop], kCFRunLoopCommonModes)); @@ -77,68 +83,131 @@ void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) { } -bool WebPage::interceptEditingKeyboardEvent(KeyboardEvent* evt, bool shouldSaveCommand) +typedef HashMap<String, String> SelectorNameMap; + +// Map selectors into Editor command names. +// This is not needed for any selectors that have the same name as the Editor command. +static const SelectorNameMap* createSelectorExceptionMap() +{ + SelectorNameMap* map = new HashMap<String, String>; + + map->add("insertNewlineIgnoringFieldEditor:", "InsertNewline"); + map->add("insertParagraphSeparator:", "InsertNewline"); + map->add("insertTabIgnoringFieldEditor:", "InsertTab"); + map->add("pageDown:", "MovePageDown"); + map->add("pageDownAndModifySelection:", "MovePageDownAndModifySelection"); + map->add("pageUp:", "MovePageUp"); + map->add("pageUpAndModifySelection:", "MovePageUpAndModifySelection"); + + return map; +} + +static String commandNameForSelectorName(const String& selectorName) +{ + // Check the exception map first. + static const SelectorNameMap* exceptionMap = createSelectorExceptionMap(); + SelectorNameMap::const_iterator it = exceptionMap->find(selectorName); + if (it != exceptionMap->end()) + return it->second; + + // Remove the trailing colon. + // No need to capitalize the command name since Editor command names are not case sensitive. + size_t selectorNameLength = selectorName.length(); + if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':') + return String(); + return selectorName.left(selectorNameLength - 1); +} + +static Frame* frameForEvent(KeyboardEvent* event) { - Node* node = evt->target()->toNode(); + Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); + return frame; +} + +bool WebPage::executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>& commands, KeyboardEvent* event) +{ + Frame* frame = frameForEvent(event); + ASSERT(frame->page() == corePage()); + + bool eventWasHandled = false; + for (size_t i = 0; i < commands.size(); ++i) { + if (commands[i].commandName == "insertText:") { + ASSERT(!frame->editor()->hasComposition()); + + if (!frame->editor()->canEdit()) + continue; + + // An insertText: might be handled by other responders in the chain if we don't handle it. + // One example is space bar that results in scrolling down the page. + eventWasHandled |= frame->editor()->insertText(commands[i].text, event); + } else { + Editor::Command command = frame->editor()->command(commandNameForSelectorName(commands[i].commandName)); + if (command.isSupported()) { + bool commandExecutedByEditor = command.execute(event); + eventWasHandled |= commandExecutedByEditor; + if (!commandExecutedByEditor) { + bool performedNonEditingBehavior = event->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown && performNonEditingBehaviorForSelector(commands[i].commandName); + eventWasHandled |= performedNonEditingBehavior; + } + } else { + bool commandWasHandledByUIProcess = false; + WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::ExecuteSavedCommandBySelector(commands[i].commandName), + Messages::WebPageProxy::ExecuteSavedCommandBySelector::Reply(commandWasHandledByUIProcess), m_pageID); + eventWasHandled |= commandWasHandledByUIProcess; + } + } + } + return eventWasHandled; +} + +bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* event, bool saveCommands) +{ + ASSERT(!saveCommands || event->keypressCommands().isEmpty()); // Save commands once for each event. + + Frame* frame = frameForEvent(event); - const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); - if (!keyEvent) + const PlatformKeyboardEvent* platformEvent = event->keyEvent(); + if (!platformEvent) return false; - const Vector<KeypressCommand>& commands = evt->keypressCommands(); - bool hasKeypressCommand = !commands.isEmpty(); - + Vector<KeypressCommand>& commands = event->keypressCommands(); + + if ([platformEvent->macEvent() type] == NSFlagsChanged) + return false; + bool eventWasHandled = false; - if (shouldSaveCommand || !hasKeypressCommand) { - Vector<KeypressCommand> commandsList; - Vector<CompositionUnderline> underlines; - unsigned start; - unsigned end; - if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretKeyEvent(keyEvent->type()), - Messages::WebPageProxy::InterpretKeyEvent::Reply(commandsList, start, end, underlines), - m_pageID, CoreIPC::Connection::NoTimeout)) + if (saveCommands) { + KeyboardEvent* oldEvent = m_keyboardEventBeingInterpreted; + m_keyboardEventBeingInterpreted = event; + bool sendResult = WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretQueuedKeyEvent(editorState()), + Messages::WebPageProxy::InterpretQueuedKeyEvent::Reply(eventWasHandled, commands), m_pageID); + m_keyboardEventBeingInterpreted = oldEvent; + if (!sendResult) + return false; + + // An input method may make several actions per keypress. For example, pressing Return with Korean IM both confirms it and sends a newline. + // IM-like actions are handled immediately (so the return value from UI process is true), but there are saved commands that + // should be handled like normal text input after DOM event dispatch. + if (!event->keypressCommands().isEmpty()) return false; - if (commandsList.isEmpty()) - return eventWasHandled; - - if (commandsList[0].commandName == "setMarkedText") { - frame->editor()->setComposition(commandsList[0].text, underlines, start, end); - eventWasHandled = true; - } else if (commandsList[0].commandName == "insertText" && frame->editor()->hasComposition()) { - frame->editor()->confirmComposition(commandsList[0].text); - eventWasHandled = true; - } else if (commandsList[0].commandName == "unmarkText") { - frame->editor()->confirmComposition(); - eventWasHandled = true; - } else { - for (size_t i = 0; i < commandsList.size(); i++) - evt->keypressCommands().append(commandsList[i]); - } } else { - size_t size = commands.size(); - // Are there commands that would just cause text insertion if executed via Editor? + // Are there commands that could just cause text insertion if executed via Editor? // WebKit doesn't have enough information about mode to decide how they should be treated, so we leave it upon WebCore // to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated // (e.g. Tab that inserts a Tab character, or Enter). bool haveTextInsertionCommands = false; - for (size_t i = 0; i < size; ++i) { - if (frame->editor()->command(commands[i].commandName).isTextInsertion()) + for (size_t i = 0; i < commands.size(); ++i) { + if (frame->editor()->command(commandNameForSelectorName(commands[i].commandName)).isTextInsertion()) haveTextInsertionCommands = true; } - if (!haveTextInsertionCommands || keyEvent->type() == PlatformKeyboardEvent::Char) { - for (size_t i = 0; i < size; ++i) { - if (commands[i].commandName == "insertText") { - // Don't insert null or control characters as they can result in unexpected behaviour - if (evt->charCode() < ' ') - return false; - eventWasHandled = frame->editor()->insertText(commands[i].text, evt); - } else - if (frame->editor()->command(commands[i].commandName).isSupported()) - eventWasHandled = frame->editor()->command(commands[i].commandName).execute(evt); - } + // If there are no text insertion commands, default keydown handler is the right time to execute the commands. + // Keypress (Char event) handler is the latest opportunity to execute. + if (!haveTextInsertionCommands || platformEvent->type() == PlatformKeyboardEvent::Char) { + eventWasHandled = executeKeypressCommandsInternal(event->keypressCommands(), event); + event->keypressCommands().clear(); } } return eventWasHandled; @@ -152,6 +221,54 @@ void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdenti } } +void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + if (frame->selection()->isContentEditable()) { + RefPtr<Range> replacementRange; + if (replacementRangeStart != NSNotFound) { + replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart)); + frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + } + + frame->editor()->setComposition(text, underlines, selectionStart, selectionEnd); + } + + newState = editorState(); +} + +void WebPage::confirmComposition(EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + frame->editor()->confirmComposition(); + + newState = editorState(); +} + +void WebPage::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + RefPtr<Range> replacementRange; + if (replacementRangeStart != NSNotFound) { + replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart)); + frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + } + + if (!frame->editor()->hasComposition()) { + // An insertText: might be handled by other responders in the chain if we don't handle it. + // One example is space bar that results in scrolling down the page. + handled = frame->editor()->insertText(text, m_keyboardEventBeingInterpreted); + } else { + handled = true; + frame->editor()->confirmComposition(text); + } + + newState = editorState(); +} + void WebPage::getMarkedRange(uint64_t& location, uint64_t& length) { location = NSNotFound; @@ -159,38 +276,59 @@ void WebPage::getMarkedRange(uint64_t& location, uint64_t& length) Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (!frame) return; - - getLocationAndLengthFromRange(frame->editor()->compositionRange().get(), location, length); -} + RefPtr<Range> range = frame->editor()->compositionRange(); + size_t locationSize; + size_t lengthSize; + if (range && TextIterator::locationAndLengthFromRange(range.get(), locationSize, lengthSize)) { + location = static_cast<uint64_t>(locationSize); + length = static_cast<uint64_t>(lengthSize); + } +} -static PassRefPtr<Range> characterRangeAtPositionForPoint(Frame* frame, const VisiblePosition& position, const IntPoint& point) +void WebPage::getSelectedRange(uint64_t& location, uint64_t& length) { - if (position.isNull()) - return 0; + location = NSNotFound; + length = 0; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; - VisiblePosition previous = position.previous(); - if (previous.isNotNull()) { - RefPtr<Range> previousCharacterRange = makeRange(previous, position); - IntRect rect = frame->editor()->firstRectForRange(previousCharacterRange.get()); - if (rect.contains(point)) - return previousCharacterRange.release(); - } - - VisiblePosition next = position.next(); - if (next.isNotNull()) { - RefPtr<Range> nextCharacterRange = makeRange(position, next); - IntRect rect = frame->editor()->firstRectForRange(nextCharacterRange.get()); - if (rect.contains(point)) - return nextCharacterRange.release(); + size_t locationSize; + size_t lengthSize; + RefPtr<Range> range = frame->selection()->toNormalizedRange(); + if (range && TextIterator::locationAndLengthFromRange(range.get(), locationSize, lengthSize)) { + location = static_cast<uint64_t>(locationSize); + length = static_cast<uint64_t>(lengthSize); } - - return 0; } -static PassRefPtr<Range> characterRangeAtPoint(Frame* frame, const IntPoint& point) +void WebPage::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result) { - return characterRangeAtPositionForPoint(frame, frame->visiblePositionForPoint(point), point); + NSRange nsRange = NSMakeRange(location, length - location); + + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + if (frame->selection()->isNone() || !frame->selection()->isContentEditable() || frame->selection()->isInPasswordField()) + return; + + RefPtr<Range> range = convertToRange(frame, nsRange); + if (!range) + return; + + result.string = [WebHTMLConverter editingAttributedStringFromRange:range.get()]; + NSAttributedString* attributedString = result.string.get(); + + // [WebHTMLConverter editingAttributedStringFromRange:] insists on inserting a trailing + // whitespace at the end of the string which breaks the ATOK input method. <rdar://problem/5400551> + // To work around this we truncate the resultant string to the correct length. + if ([attributedString length] > nsRange.length) { + ASSERT([attributedString length] == nsRange.length + 1); + ASSERT([[attributedString string] characterAtIndex:nsRange.length] == '\n' || [[attributedString string] characterAtIndex:nsRange.length] == ' '); + result.string = [attributedString attributedSubstringFromRange:NSMakeRange(0, nsRange.length)]; + } } void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index) @@ -203,15 +341,17 @@ void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index) HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false); frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); - RefPtr<Range> range = characterRangeAtPoint(frame, result.point()); + RefPtr<Range> range = frame->rangeForPoint(result.point()); if (!range) return; - uint64_t length; - getLocationAndLengthFromRange(range.get(), index, length); + size_t location; + size_t length; + if (TextIterator::locationAndLengthFromRange(range.get(), location, length)) + index = static_cast<uint64_t>(location); } -static PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange) +PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange) { if (nsrange.location > INT_MAX) return 0; @@ -246,6 +386,12 @@ void WebPage::firstRectForCharacterRange(uint64_t location, uint64_t length, Web resultRect = frame->view()->contentsToWindow(rect); } +void WebPage::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands, bool& handled, EditorState& newState) +{ + handled = executeKeypressCommandsInternal(commands, m_keyboardEventBeingInterpreted); + newState = editorState(); +} + static bool isPositionInRange(const VisiblePosition& position, Range* range) { RefPtr<Range> positionRange = makeRange(position, position); @@ -284,12 +430,12 @@ void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint) frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); IntPoint translatedPoint = frame->view()->windowToContents(point); - VisiblePosition position = frame->visiblePositionForPoint(translatedPoint); // Don't do anything if there is no character at the point. - if (!characterRangeAtPositionForPoint(frame, position, translatedPoint)) + if (!frame->rangeForPoint(translatedPoint)) return; + VisiblePosition position = frame->visiblePositionForPoint(translatedPoint); VisibleSelection selection = m_page->focusController()->focusedOrMainFrame()->selection()->selection(); if (shouldUseSelection(position, selection)) { performDictionaryLookupForSelection(DictionaryPopupInfo::HotKey, frame, selection); @@ -378,96 +524,54 @@ void WebPage::performDictionaryLookupForRange(DictionaryPopupInfo::Type type, Fr dictionaryPopupInfo.type = type; dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y()); dictionaryPopupInfo.fontInfo.fontAttributeDictionary = fontDescriptorAttributes; +#if !defined(BUILDING_ON_SNOW_LEOPARD) dictionaryPopupInfo.options = (CFDictionaryRef)options; +#endif send(Messages::WebPageProxy::DidPerformDictionaryLookup(rangeText, dictionaryPopupInfo)); } -bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) +bool WebPage::performNonEditingBehaviorForSelector(const String& selector) { - if (keyboardEvent.type() != WebEvent::KeyDown) - return false; - - // FIXME: This should be in WebCore. - - switch (keyboardEvent.windowsVirtualKeyCode()) { - case VK_BACK: - if (keyboardEvent.shiftKey()) - m_page->goForward(); - else - m_page->goBack(); - break; - case VK_SPACE: - if (keyboardEvent.shiftKey()) - logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage); - else - logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage); - break; - case VK_PRIOR: - logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage); - break; - case VK_NEXT: - logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage); - break; - case VK_HOME: - logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument); - break; - case VK_END: - logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument); - break; - case VK_UP: - if (keyboardEvent.shiftKey()) - return false; - if (keyboardEvent.metaKey()) { - scroll(m_page.get(), ScrollUp, ScrollByDocument); - scroll(m_page.get(), ScrollLeft, ScrollByDocument); - } else if (keyboardEvent.altKey() || keyboardEvent.controlKey()) - scroll(m_page.get(), ScrollUp, ScrollByPage); - else - scroll(m_page.get(), ScrollUp, ScrollByLine); - break; - case VK_DOWN: - if (keyboardEvent.shiftKey()) - return false; - if (keyboardEvent.metaKey()) { - scroll(m_page.get(), ScrollDown, ScrollByDocument); - scroll(m_page.get(), ScrollLeft, ScrollByDocument); - } else if (keyboardEvent.altKey() || keyboardEvent.controlKey()) - scroll(m_page.get(), ScrollDown, ScrollByPage); - else - scroll(m_page.get(), ScrollDown, ScrollByLine); - break; - case VK_LEFT: - if (keyboardEvent.shiftKey()) - return false; - if (keyboardEvent.metaKey()) - m_page->goBack(); - else { - if (keyboardEvent.altKey() || keyboardEvent.controlKey()) - scroll(m_page.get(), ScrollLeft, ScrollByPage); - else - scroll(m_page.get(), ScrollLeft, ScrollByLine); - } - break; - case VK_RIGHT: - if (keyboardEvent.shiftKey()) - return false; - if (keyboardEvent.metaKey()) - m_page->goForward(); - else { - if (keyboardEvent.altKey() || keyboardEvent.controlKey()) - scroll(m_page.get(), ScrollRight, ScrollByPage); - else - scroll(m_page.get(), ScrollRight, ScrollByLine); - } - break; - default: + // FIXME: All these selectors have corresponding Editor commands, but the commands only work in editable content. + // Should such non-editing behaviors be implemented in Editor or EventHandler::defaultArrowEventHandler() perhaps? + if (selector == "moveUp:") + scroll(m_page.get(), ScrollUp, ScrollByLine); + else if (selector == "moveToBeginningOfParagraph:") + scroll(m_page.get(), ScrollUp, ScrollByPage); + else if (selector == "moveToBeginningOfDocument:") { + scroll(m_page.get(), ScrollUp, ScrollByDocument); + scroll(m_page.get(), ScrollLeft, ScrollByDocument); + } else if (selector == "moveDown:") + scroll(m_page.get(), ScrollDown, ScrollByLine); + else if (selector == "moveToEndOfParagraph:") + scroll(m_page.get(), ScrollDown, ScrollByPage); + else if (selector == "moveToEndOfDocument:") { + scroll(m_page.get(), ScrollDown, ScrollByDocument); + scroll(m_page.get(), ScrollLeft, ScrollByDocument); + } else if (selector == "moveLeft:") + scroll(m_page.get(), ScrollLeft, ScrollByLine); + else if (selector == "moveWordLeft:") + scroll(m_page.get(), ScrollLeft, ScrollByPage); + else if (selector == "moveToLeftEndOfLine:") + m_page->goBack(); + else if (selector == "moveRight:") + scroll(m_page.get(), ScrollRight, ScrollByLine); + else if (selector == "moveWordRight:") + scroll(m_page.get(), ScrollRight, ScrollByPage); + else if (selector == "moveToRightEndOfLine:") + m_page->goForward(); + else return false; - } return true; } +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&) +{ + return false; +} + void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken) { #if !defined(BUILDING_ON_SNOW_LEOPARD) @@ -484,6 +588,10 @@ void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes, bool& result) { Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || frame->selection()->isNone()) { + result = false; + return; + } frame->editor()->writeSelectionToPasteboard(pasteboardName, pasteboardTypes); result = true; } @@ -491,6 +599,10 @@ void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vec void WebPage::readSelectionFromPasteboard(const String& pasteboardName, bool& result) { Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || frame->selection()->isNone()) { + result = false; + return; + } frame->editor()->readSelectionFromPasteboard(pasteboardName); result = true; } @@ -548,10 +660,39 @@ void WebPage::setDragSource(NSObject *dragSource) void WebPage::platformDragEnded() { + // The draggedImage method releases its responder; we retain here to balance that. + [m_dragSource.get() retain]; // The drag source we care about here is NSFilePromiseDragSource, which doesn't look at // the arguments. It's OK to just pass arbitrary constant values, so we just pass all zeroes. [m_dragSource.get() draggedImage:nil endedAt:NSZeroPoint operation:NSDragOperationNone]; m_dragSource = nullptr; } +void WebPage::shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent& event, bool& result) +{ + result = false; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true); + if (hitResult.isSelected()) + result = frame->eventHandler()->eventMayStartDrag(platform(event)); +} + +void WebPage::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event, bool& result) +{ + result = false; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true); + frame->eventHandler()->setActivationEventNumber(eventNumber); + if (hitResult.isSelected()) + result = frame->eventHandler()->eventMayStartDrag(platform(event)); + else + result = !!hitResult.scrollbar(); +} + } // namespace WebKit |