📄 webview.cpp
字号:
for (unsigned i = 0; i < _countof(keyPressEntries); i++) keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); } unsigned modifiers = 0; if (evt->shiftKey()) modifiers |= ShiftKey; if (evt->altKey()) modifiers |= AltKey; if (evt->ctrlKey()) modifiers |= CtrlKey; if (evt->type() == eventNames().keydownEvent) { int mapKey = modifiers << 16 | evt->keyCode(); return mapKey ? keyDownCommandsMap->get(mapKey) : 0; } int mapKey = modifiers << 16 | evt->charCode(); return mapKey ? keyPressCommandsMap->get(mapKey) : 0;}bool WebView::handleEditingKeyboardEvent(KeyboardEvent* evt){ Node* node = evt->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); if (!keyEvent || keyEvent->isSystemKey()) // do not treat this as text input if it's a system key event return false; Editor::Command command = frame->editor()->command(interpretKeyEvent(evt)); if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor 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). return !command.isTextInsertion() && command.execute(evt); } if (command.execute(evt)) return true; // Don't insert null or control characters as they can result in unexpected behaviour if (evt->charCode() < ' ') return false; return frame->editor()->insertText(evt->keyEvent()->text(), evt);}bool WebView::keyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown){ Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (virtualKeyCode == VK_CAPITAL) frame->eventHandler()->capsLockStateMayHaveChanged(); PlatformKeyboardEvent keyEvent(m_viewWindow, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown); bool handled = frame->eventHandler()->keyEvent(keyEvent); // These events cannot be canceled, and we have no default handling for them. // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>. if (systemKeyDown && virtualKeyCode != VK_RETURN) return false; if (handled) { // FIXME: remove WM_UNICHAR, too MSG msg; // WM_SYSCHAR events should not be removed, because access keys are implemented in WebCore in WM_SYSCHAR handler. if (!systemKeyDown) ::PeekMessage(&msg, m_viewWindow, WM_CHAR, WM_CHAR, PM_REMOVE); return true; } // We need to handle back/forward using either Backspace(+Shift) or Ctrl+Left/Right Arrow keys. if ((virtualKeyCode == VK_BACK && keyEvent.shiftKey()) || (virtualKeyCode == VK_RIGHT && keyEvent.ctrlKey())) m_page->goForward(); else if (virtualKeyCode == VK_BACK || (virtualKeyCode == VK_LEFT && keyEvent.ctrlKey())) m_page->goBack(); // Need to scroll the page if the arrow keys, pgup/dn, or home/end are hit. ScrollDirection direction; ScrollGranularity granularity; switch (virtualKeyCode) { case VK_LEFT: granularity = ScrollByLine; direction = ScrollLeft; break; case VK_RIGHT: granularity = ScrollByLine; direction = ScrollRight; break; case VK_UP: granularity = ScrollByLine; direction = ScrollUp; break; case VK_DOWN: granularity = ScrollByLine; direction = ScrollDown; break; case VK_HOME: granularity = ScrollByDocument; direction = ScrollUp; break; case VK_END: granularity = ScrollByDocument; direction = ScrollDown; break; case VK_PRIOR: granularity = ScrollByPage; direction = ScrollUp; break; case VK_NEXT: granularity = ScrollByPage; direction = ScrollDown; break; default: return false; } if (!frame->eventHandler()->scrollOverflow(direction, granularity)) { handled = frame->view()->scroll(direction, granularity); Frame* parent = frame->tree()->parent(); while(!handled && parent) { handled = parent->view()->scroll(direction, granularity); parent = parent->tree()->parent(); } } return handled;}bool WebView::keyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown){ Frame* frame = m_page->focusController()->focusedOrMainFrame(); PlatformKeyboardEvent keyEvent(m_viewWindow, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown); // IE does not dispatch keypress event for WM_SYSCHAR. if (systemKeyDown) return frame->eventHandler()->handleAccessKey(keyEvent); return frame->eventHandler()->keyEvent(keyEvent);}bool WebView::inResizer(LPARAM lParam){ if (!m_uiDelegatePrivate) return false; RECT r; if (FAILED(m_uiDelegatePrivate->webViewResizerRect(this, &r))) return false; POINT pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); return !!PtInRect(&r, pt);}static bool registerWebViewWindowClass(){ static bool haveRegisteredWindowClass = false; if (haveRegisteredWindowClass) return true; haveRegisteredWindowClass = true; WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_DBLCLKS; wcex.lpfnWndProc = WebViewWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 4; // 4 bytes for the IWebView pointer wcex.hInstance = gInstance; wcex.hIcon = 0; wcex.hCursor = ::LoadCursor(0, IDC_ARROW); wcex.hbrBackground = 0; wcex.lpszMenuName = 0; wcex.lpszClassName = kWebViewWindowClassName; wcex.hIconSm = 0; return !!RegisterClassEx(&wcex);}namespace WebCore { extern HCURSOR lastSetCursor;}static HWND findTopLevelParent(HWND window){ if (!window) return 0; HWND current = window; for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent)) if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD))) return current; ASSERT_NOT_REACHED(); return 0;}static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ LRESULT lResult = 0; LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); WebView* webView = reinterpret_cast<WebView*>(longPtr); WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0; if (!mainFrameImpl || webView->isBeingDestroyed()) return DefWindowProc(hWnd, message, wParam, lParam); // hold a ref, since the WebView could go away in an event handler. COMPtr<WebView> protector(webView); ASSERT(webView); // Windows Media Player has a modal message loop that will deliver messages // to us at inappropriate times and we will crash if we handle them when // they are delivered. We repost paint messages so that we eventually get // a chance to paint once the modal loop has exited, but other messages // aren't safe to repost, so we just drop them. if (PluginView::isCallingPlugin()) { if (message == WM_PAINT) PostMessage(hWnd, message, wParam, lParam); return 0; } bool handled = true; switch (message) { case WM_PAINT: { webView->paint(0, 0); break; } case WM_PRINTCLIENT: webView->paint((HDC)wParam, lParam); break; case WM_DESTROY: webView->close(); webView->setIsBeingDestroyed(); webView->revokeDragDrop(); break; case WM_MOUSEMOVE: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_MOUSELEAVE: if (Frame* coreFrame = core(mainFrameImpl)) if (coreFrame->view()->didFirstLayout()) handled = webView->handleMouseEvent(message, wParam, lParam); break; case WM_MOUSEWHEEL: case WM_VISTA_MOUSEHWHEEL: if (Frame* coreFrame = core(mainFrameImpl)) if (coreFrame->view()->didFirstLayout()) handled = webView->mouseWheel(wParam, lParam, (wParam & MK_SHIFT) || message == WM_VISTA_MOUSEHWHEEL); break; case WM_SYSKEYDOWN: handled = webView->keyDown(wParam, lParam, true); break; case WM_KEYDOWN: handled = webView->keyDown(wParam, lParam); break; case WM_SYSKEYUP: handled = webView->keyUp(wParam, lParam, true); break; case WM_KEYUP: handled = webView->keyUp(wParam, lParam); break; case WM_SYSCHAR: handled = webView->keyPress(wParam, lParam, true); break; case WM_CHAR: handled = webView->keyPress(wParam, lParam); break; // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits). case WM_SIZE: if (webView->isBeingDestroyed()) // If someone has sent us this message while we're being destroyed, we should bail out so we don't crash. break; if (lParam != 0) { webView->deleteBackingStore(); if (Frame* coreFrame = core(mainFrameImpl)) coreFrame->view()->resize(LOWORD(lParam), HIWORD(lParam)); } break; case WM_SHOWWINDOW: lResult = DefWindowProc(hWnd, message, wParam, lParam); if (wParam == 0) // The window is being hidden (e.g., because we switched tabs. // Null out our backing store. webView->deleteBackingStore(); break; case WM_SETFOCUS: { COMPtr<IWebUIDelegate> uiDelegate; COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) uiDelegatePrivate->webViewReceivedFocus(webView); FocusController* focusController = webView->page()->focusController(); if (Frame* frame = focusController->focusedFrame()) { // Send focus events unless the previously focused window is a // child of ours (for example a plugin). if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam))) frame->selection()->setFocused(true); } else focusController->setFocusedFrame(webView->page()->mainFrame()); break; } case WM_KILLFOCUS: { COMPtr<IWebUIDelegate> uiDelegate; COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; HWND newFocusWnd = reinterpret_cast<HWND>(wParam); if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd); FocusController* focusController = webView->page()->focusController(); Frame* frame = focusController->focusedOrMainFrame(); webView->resetIME(frame); // Send blur events unless we're losing focus to a child of ours. if (!IsChild(hWnd, newFocusWnd)) frame->selection()->setFocused(false); break; } case WM_WINDOWPOSCHANGED: if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW) webView->updateActiveStateSoon(); handled = false; break; case WM_CUT: webView->cut(0); break; case WM_COPY: webView->copy(0); break; case WM_PASTE: webView->paste(0); break; case WM_CLEAR: webView->delete_(0); break; case WM_COMMAND: if (HIWORD(wParam)) handled = webView->execCommand(wParam, lParam); else // If the high word of wParam is 0, the message is from a menu webView->performContextMenuAction(wParam, lParam, false); break; case WM_MENUCOMMAND: webView->performContextMenuAction(wParam, lParam, true); break; case WM_CONTEXTMENU: handled = webView->handleContextMenuEvent(wParam, lParam)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -