2023
2024bool EventHandler::sendContextMenuEventForKey()
2025{
2026 FrameView* view = m_frame->view();
2027 if (!view)
2028 return false;
2029
2030 Document* doc = m_frame->document();
2031 if (!doc)
2032 return false;
2033
2034 static const int kContextMenuMargin = 1;
2035
2036#if OS(WINDOWS)
2037 int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT);
2038#else
2039 int rightAligned = 0;
2040#endif
2041 IntPoint location;
2042
2043 Node* focusedNode = doc->focusedNode();
2044 SelectionController* selectionController = m_frame->selection();
2045 Position start = selectionController->selection().start();
2046
2047 if (start.node() && (selectionController->rootEditableElement() || selectionController->isRange())) {
2048 RenderObject* renderer = start.node()->renderer();
2049 if (!renderer)
2050 return false;
2051
2052 RefPtr<Range> selection = selectionController->toNormalizedRange();
2053 IntRect firstRect = m_frame->firstRectForRange(selection.get());
2054
2055 int x = rightAligned ? firstRect.right() : firstRect.x();
2056 location = IntPoint(x, firstRect.bottom());
2057 } else if (focusedNode) {
2058 RenderBoxModelObject* box = focusedNode->renderBoxModelObject();
2059 IntRect clippedRect = box->absoluteClippedOverflowRect();
2060 location = clippedRect.bottomLeft();
2061 } else {
2062 location = IntPoint(
2063 rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin,
2064 kContextMenuMargin);
2065 }
2066
2067 m_frame->view()->setCursor(pointerCursor());
2068
2069 IntPoint position = view->contentsToWindow(location);
2070 IntPoint globalPosition = view->contentsToScreen(IntRect(location, IntSize())).location();
2071
2072 Node* targetNode = doc->focusedNode();
2073 if (!targetNode)
2074 targetNode = doc;
2075
2076 // Use the focused node as the target for hover and active.
2077 HitTestResult result(position);
2078 result.setInnerNode(targetNode);
2079 HitTestRequest request(HitTestRequest::Active);
2080 doc->renderView()->layer()->updateHoverActiveState(request, result);
2081 doc->updateStyleIfNeeded();
2082
2083 // The contextmenu event is a mouse event even when invoked using the keyboard.
2084 // This is required for web compatibility.
2085
2086#if OS(WINDOWS)
2087 MouseEventType eventType = MouseEventReleased;
2088#else
2089 MouseEventType eventType = MouseEventPressed;
2090#endif
2091
2092 PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime());
2093
2094 return dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, mouseEvent, false);
2095}
2096