📄 webview.cpp
字号:
} lParam = MAKELPARAM(coords.x, coords.y); // The contextMenuController() holds onto the last context menu that was popped up on the // page until a new one is created. We need to clear this menu before propagating the event // through the DOM so that we can detect if we create a new menu for this event, since we // won't create a new menu if the DOM swallows the event and the defaultEventHandler does // not run. m_page->contextMenuController()->clearContextMenu(); IntPoint documentPoint(m_page->mainFrame()->view()->windowToContents(coords)); HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(documentPoint, false); Frame* targetFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); targetFrame->view()->setCursor(pointerCursor()); PlatformMouseEvent mouseEvent(m_viewWindow, WM_RBUTTONUP, wParam, lParam); bool handledEvent = targetFrame->eventHandler()->sendContextMenuEvent(mouseEvent); if (!handledEvent) return false; // Show the menu ContextMenu* coreMenu = m_page->contextMenuController()->contextMenu(); if (!coreMenu) return false; Node* node = coreMenu->hitTestResult().innerNonSharedNode(); if (!node) return false; Frame* frame = node->document()->frame(); if (!frame) return false; FrameView* view = frame->view(); if (!view) return false; POINT point(view->contentsToWindow(coreMenu->hitTestResult().point())); // Translate the point to screen coordinates if (!::ClientToScreen(m_viewWindow, &point)) return false; BOOL hasCustomMenus = false; if (m_uiDelegate) m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); if (hasCustomMenus) m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->platformDescription(), &point); else { // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL | TPM_LEFTALIGN | TPM_HORPOSANIMATION; ::TrackPopupMenuEx(coreMenu->platformDescription(), flags, point.x, point.y, m_viewWindow, 0); } return true;}bool WebView::onMeasureItem(WPARAM /*wParam*/, LPARAM lParam){ if (!m_uiDelegate) return false; BOOL hasCustomMenus = false; m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); if (!hasCustomMenus) return false; m_uiDelegate->measureCustomMenuItem((IWebView*)this, (void*)lParam); return true;}bool WebView::onDrawItem(WPARAM /*wParam*/, LPARAM lParam){ if (!m_uiDelegate) return false; BOOL hasCustomMenus = false; m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); if (!hasCustomMenus) return false; m_uiDelegate->drawCustomMenuItem((IWebView*)this, (void*)lParam); return true;}bool WebView::onInitMenuPopup(WPARAM wParam, LPARAM /*lParam*/){ if (!m_uiDelegate) return false; HMENU menu = (HMENU)wParam; if (!menu) return false; BOOL hasCustomMenus = false; m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); if (!hasCustomMenus) return false; m_uiDelegate->addCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu); return true;}bool WebView::onUninitMenuPopup(WPARAM wParam, LPARAM /*lParam*/){ if (!m_uiDelegate) return false; HMENU menu = (HMENU)wParam; if (!menu) return false; BOOL hasCustomMenus = false; m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus); if (!hasCustomMenus) return false; m_uiDelegate->cleanUpCustomMenuDrawingData((IWebView*)this, (OLE_HANDLE)(ULONG64)menu); return true;}void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosition){ ContextMenu* menu = m_page->contextMenuController()->contextMenu(); ASSERT(menu); ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam, (HMENU)lParam) : menu->itemWithAction((ContextMenuAction)wParam); if (!item) return; m_page->contextMenuController()->contextMenuItemSelected(item); delete item;}bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam){ static LONG globalClickCount; static IntPoint globalPrevPoint; static MouseButton globalPrevButton; static LONG globalPrevMouseDownTime; // Create our event. // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position // of the event to be at (MINSHORT, MINSHORT). LPARAM position = (message == WM_MOUSELEAVE) ? ((MINSHORT << 16) | MINSHORT) : lParam; PlatformMouseEvent mouseEvent(m_viewWindow, message, wParam, position, m_mouseActivated); bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) && abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK); LONG messageTime = ::GetMessageTime(); if (inResizer(position)) { if (m_uiDelegate) { COMPtr<IWebUIDelegatePrivate4> uiPrivate(Query, m_uiDelegate); if (uiPrivate) uiPrivate->webViewSendResizeMessage(message, wParam, position); } return true; } bool handled = false; if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) { // FIXME: I'm not sure if this is the "right" way to do this // but without this call, we never become focused since we don't allow // the default handling of mouse events. SetFocus(m_viewWindow); // Always start capturing events when the mouse goes down in our HWND. ::SetCapture(m_viewWindow); if (((messageTime - globalPrevMouseDownTime) < (LONG)::GetDoubleClickTime()) && insideThreshold && mouseEvent.button() == globalPrevButton) globalClickCount++; else // Reset the click count. globalClickCount = 1; globalPrevMouseDownTime = messageTime; globalPrevButton = mouseEvent.button(); globalPrevPoint = mouseEvent.pos(); mouseEvent.setClickCount(globalClickCount); handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) { globalClickCount++; mouseEvent.setClickCount(globalClickCount); handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) { // Record the global position and the button of the up. globalPrevButton = mouseEvent.button(); globalPrevPoint = mouseEvent.pos(); mouseEvent.setClickCount(globalClickCount); m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent); ::ReleaseCapture(); } else if (message == WM_MOUSELEAVE && m_mouseOutTracker) { // Once WM_MOUSELEAVE is fired windows clears this tracker // so there is no need to disable it ourselves. m_mouseOutTracker.set(0); m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent); handled = true; } else if (message == WM_MOUSEMOVE) { if (!insideThreshold) globalClickCount = 0; mouseEvent.setClickCount(globalClickCount); handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent); if (!m_mouseOutTracker) { m_mouseOutTracker.set(new TRACKMOUSEEVENT); m_mouseOutTracker->cbSize = sizeof(TRACKMOUSEEVENT); m_mouseOutTracker->dwFlags = TME_LEAVE; m_mouseOutTracker->hwndTrack = m_viewWindow; ::TrackMouseEvent(m_mouseOutTracker.get()); } } setMouseActivated(false); return handled;}bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isHorizontal){ // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their // own local zoom modes for Ctrl+wheel). if (wParam & MK_CONTROL) { short delta = short(HIWORD(wParam)); if (delta < 0) makeTextLarger(0); else makeTextSmaller(0); return true; } PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isHorizontal); Frame* coreFrame = core(m_mainFrame); if (!coreFrame) return false; return coreFrame->eventHandler()->handleWheelEvent(wheelEvent);}bool WebView::execCommand(WPARAM wParam, LPARAM /*lParam*/){ Frame* frame = m_page->focusController()->focusedOrMainFrame(); switch (LOWORD(wParam)) { case SelectAll: return frame->editor()->command("SelectAll").execute(); case Undo: return frame->editor()->command("Undo").execute(); case Redo: return frame->editor()->command("Redo").execute(); } return false;}bool WebView::keyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown){ PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown); Frame* frame = m_page->focusController()->focusedOrMainFrame(); m_currentCharacterCode = 0; return frame->eventHandler()->keyEvent(keyEvent);}static const unsigned CtrlKey = 1 << 0;static const unsigned AltKey = 1 << 1;static const unsigned ShiftKey = 1 << 2;struct KeyDownEntry { unsigned virtualKey; unsigned modifiers; const char* name;};struct KeyPressEntry { unsigned charCode; unsigned modifiers; const char* name;};static const KeyDownEntry keyDownEntries[] = { { VK_LEFT, 0, "MoveLeft" }, { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, { VK_LEFT, CtrlKey, "MoveWordLeft" }, { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, { VK_RIGHT, 0, "MoveRight" }, { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, { VK_RIGHT, CtrlKey, "MoveWordRight" }, { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, { VK_UP, 0, "MoveUp" }, { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, { VK_DOWN, 0, "MoveDown" }, { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, { VK_PRIOR, 0, "MovePageUp" }, { VK_NEXT, 0, "MovePageDown" }, { VK_HOME, 0, "MoveToBeginningOfLine" }, { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, { VK_END, 0, "MoveToEndOfLine" }, { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, { VK_END, CtrlKey, "MoveToEndOfDocument" }, { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, { VK_BACK, 0, "DeleteBackward" }, { VK_BACK, ShiftKey, "DeleteBackward" }, { VK_DELETE, 0, "DeleteForward" }, { VK_BACK, CtrlKey, "DeleteWordBackward" }, { VK_DELETE, CtrlKey, "DeleteWordForward" }, { 'B', CtrlKey, "ToggleBold" }, { 'I', CtrlKey, "ToggleItalic" }, { VK_ESCAPE, 0, "Cancel" }, { VK_OEM_PERIOD, CtrlKey, "Cancel" }, { VK_TAB, 0, "InsertTab" }, { VK_TAB, ShiftKey, "InsertBacktab" }, { VK_RETURN, 0, "InsertNewline" }, { VK_RETURN, CtrlKey, "InsertNewline" }, { VK_RETURN, AltKey, "InsertNewline" }, { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled // in the application or in WebKit. We chose WebKit. { 'C', CtrlKey, "Copy" }, { 'V', CtrlKey, "Paste" }, { 'X', CtrlKey, "Cut" }, { 'A', CtrlKey, "SelectAll" }, { VK_INSERT, CtrlKey, "Copy" }, { VK_DELETE, ShiftKey, "Cut" }, { VK_INSERT, ShiftKey, "Paste" }, { 'Z', CtrlKey, "Undo" }, { 'Z', CtrlKey | ShiftKey, "Redo" },};static const KeyPressEntry keyPressEntries[] = { { '\t', 0, "InsertTab" }, { '\t', ShiftKey, "InsertBacktab" }, { '\r', 0, "InsertNewline" }, { '\r', CtrlKey, "InsertNewline" }, { '\r', AltKey, "InsertNewline" }, { '\r', AltKey | ShiftKey, "InsertNewline" },};const char* WebView::interpretKeyEvent(const KeyboardEvent* evt){ ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); static HashMap<int, const char*>* keyDownCommandsMap = 0; static HashMap<int, const char*>* keyPressCommandsMap = 0; if (!keyDownCommandsMap) { keyDownCommandsMap = new HashMap<int, const char*>; keyPressCommandsMap = new HashMap<int, const char*>; for (unsigned i = 0; i < _countof(keyDownEntries); i++) keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -