📄 webview.cpp
字号:
HDC windowDC = ::GetDC(m_viewWindow); HDC bitmapDC = ::CreateCompatibleDC(windowDC); ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); // Scroll the bitmap. RECT scrollRectWin(scrollViewRect); RECT clipRectWin(clipRect); ::ScrollDC(bitmapDC, dx, dy, &scrollRectWin, &clipRectWin, updateRegion, 0); RECT regionBox; ::GetRgnBox(updateRegion, ®ionBox); // Flush. GdiFlush(); // Add the dirty region to the backing store's dirty region. addToDirtyRegion(updateRegion); if (m_uiDelegatePrivate) m_uiDelegatePrivate->webViewScrolled(this); // Update the backing store. updateBackingStore(frameView, bitmapDC, false); // Clean up. ::DeleteDC(bitmapDC); ::ReleaseDC(m_viewWindow, windowDC);}// This emulates the Mac smarts for painting rects intelligently. This is very// important for us, since we double buffer based off dirty rects.static void getUpdateRects(HRGN region, const IntRect& dirtyRect, Vector<IntRect>& rects){ ASSERT_ARG(region, region); const int cRectThreshold = 10; const float cWastedSpaceThreshold = 0.75f; rects.clear(); DWORD regionDataSize = GetRegionData(region, sizeof(RGNDATA), NULL); if (!regionDataSize) { rects.append(dirtyRect); return; } Vector<unsigned char> buffer(regionDataSize); RGNDATA* regionData = reinterpret_cast<RGNDATA*>(buffer.data()); GetRegionData(region, regionDataSize, regionData); if (regionData->rdh.nCount > cRectThreshold) { rects.append(dirtyRect); return; } double singlePixels = 0.0; unsigned i; RECT* rect; for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++) singlePixels += (rect->right - rect->left) * (rect->bottom - rect->top); double unionPixels = dirtyRect.width() * dirtyRect.height(); double wastedSpace = 1.0 - (singlePixels / unionPixels); if (wastedSpace <= cWastedSpaceThreshold) { rects.append(dirtyRect); return; } for (i = 0, rect = reinterpret_cast<RECT*>(regionData->Buffer); i < regionData->rdh.nCount; i++, rect++) rects.append(*rect);}void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStoreCompletelyDirty, WindowsToPaint windowsToPaint){ LOCAL_GDI_COUNTER(0, __FUNCTION__); HDC windowDC = 0; HDC bitmapDC = dc; if (!dc) { windowDC = ::GetDC(m_viewWindow); bitmapDC = ::CreateCompatibleDC(windowDC); ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); } if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) { // Do a layout first so that everything we render to the backing store is always current. if (Frame* coreFrame = core(m_mainFrame)) if (FrameView* view = coreFrame->view()) view->layoutIfNeededRecursive(); Vector<IntRect> paintRects; if (!backingStoreCompletelyDirty) { RECT regionBox; ::GetRgnBox(m_backingStoreDirtyRegion.get(), ®ionBox); getUpdateRects(m_backingStoreDirtyRegion.get(), regionBox, paintRects); } else { RECT clientRect; ::GetClientRect(m_viewWindow, &clientRect); paintRects.append(clientRect); } for (unsigned i = 0; i < paintRects.size(); ++i) paintIntoBackingStore(frameView, bitmapDC, paintRects[i], windowsToPaint); if (m_uiDelegatePrivate) { COMPtr<IWebUIDelegatePrivate2> uiDelegatePrivate2(Query, m_uiDelegatePrivate); if (uiDelegatePrivate2) uiDelegatePrivate2->webViewPainted(this); } m_backingStoreDirtyRegion.clear(); } if (!dc) { ::DeleteDC(bitmapDC); ::ReleaseDC(m_viewWindow, windowDC); } GdiFlush();}void WebView::paint(HDC dc, LPARAM options){ LOCAL_GDI_COUNTER(0, __FUNCTION__); Frame* coreFrame = core(m_mainFrame); if (!coreFrame) return; FrameView* frameView = coreFrame->view(); m_paintCount++; RECT rcPaint; HDC hdc; OwnPtr<HRGN> region; int regionType = NULLREGION; PAINTSTRUCT ps; WindowsToPaint windowsToPaint; if (!dc) { region.set(CreateRectRgn(0,0,0,0)); regionType = GetUpdateRgn(m_viewWindow, region.get(), false); hdc = BeginPaint(m_viewWindow, &ps); rcPaint = ps.rcPaint; // We're painting to the screen, and our child windows can handle // painting themselves to the screen. windowsToPaint = PaintWebViewOnly; } else { hdc = dc; ::GetClientRect(m_viewWindow, &rcPaint); if (options & PRF_ERASEBKGND) ::FillRect(hdc, &rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH)); // Since we aren't painting to the screen, we want to paint all our // children into the HDC. windowsToPaint = PaintWebViewAndChildren; } HDC bitmapDC = ::CreateCompatibleDC(hdc); bool backingStoreCompletelyDirty = ensureBackingStore(); ::SelectObject(bitmapDC, m_backingStoreBitmap.get()); // Update our backing store if needed. updateBackingStore(frameView, bitmapDC, backingStoreCompletelyDirty, windowsToPaint); // Now we blit the updated backing store IntRect windowDirtyRect = rcPaint; // Apply the same heuristic for this update region too. Vector<IntRect> blitRects; if (region && regionType == COMPLEXREGION) getUpdateRects(region.get(), windowDirtyRect, blitRects); else blitRects.append(windowDirtyRect); for (unsigned i = 0; i < blitRects.size(); ++i) paintIntoWindow(bitmapDC, hdc, blitRects[i]); ::DeleteDC(bitmapDC); // Paint the gripper. COMPtr<IWebUIDelegate> ui; if (SUCCEEDED(uiDelegate(&ui))) { COMPtr<IWebUIDelegatePrivate> uiPrivate; if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) { RECT r; if (SUCCEEDED(uiPrivate->webViewResizerRect(this, &r))) { LOCAL_GDI_COUNTER(2, __FUNCTION__" webViewDrawResizer delegate call"); uiPrivate->webViewDrawResizer(this, hdc, (frameView->containsScrollbarsAvoidingResizer() ? true : false), &r); } } } if (!dc) EndPaint(m_viewWindow, &ps); m_paintCount--; if (active()) cancelDeleteBackingStoreSoon(); else deleteBackingStoreSoon();}void WebView::paintIntoBackingStore(FrameView* frameView, HDC bitmapDC, const IntRect& dirtyRect, WindowsToPaint windowsToPaint){ LOCAL_GDI_COUNTER(0, __FUNCTION__); RECT rect = dirtyRect;#if FLASH_BACKING_STORE_REDRAW HDC dc = ::GetDC(m_viewWindow); OwnPtr<HBRUSH> yellowBrush = CreateSolidBrush(RGB(255, 255, 0)); FillRect(dc, &rect, yellowBrush.get()); GdiFlush(); Sleep(50); paintIntoWindow(bitmapDC, dc, dirtyRect); ::ReleaseDC(m_viewWindow, dc);#endif GraphicsContext gc(bitmapDC, m_transparent); gc.setShouldIncludeChildWindows(windowsToPaint == PaintWebViewAndChildren); gc.save(); if (m_transparent) gc.clearRect(dirtyRect); else FillRect(bitmapDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); if (frameView && frameView->frame() && frameView->frame()->contentRenderer()) { gc.clip(dirtyRect); frameView->paint(&gc, dirtyRect); } gc.restore();}void WebView::paintIntoWindow(HDC bitmapDC, HDC windowDC, const IntRect& dirtyRect){ LOCAL_GDI_COUNTER(0, __FUNCTION__);#if FLASH_WINDOW_REDRAW OwnPtr<HBRUSH> greenBrush = CreateSolidBrush(RGB(0, 255, 0)); RECT rect = dirtyRect; FillRect(windowDC, &rect, greenBrush.get()); GdiFlush(); Sleep(50);#endif // Blit the dirty rect from the backing store into the same position // in the destination DC. BitBlt(windowDC, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), bitmapDC, dirtyRect.x(), dirtyRect.y(), SRCCOPY);}void WebView::frameRect(RECT* rect){ ::GetWindowRect(m_viewWindow, rect);}void WebView::closeWindowSoon(){ m_closeWindowTimer.startOneShot(0); AddRef();}void WebView::closeWindowTimerFired(WebCore::Timer<WebView>*){ closeWindow(); Release();}void WebView::closeWindow(){ if (m_hasSpellCheckerDocumentTag) { if (m_editingDelegate) m_editingDelegate->closeSpellDocument(this); m_hasSpellCheckerDocumentTag = false; } COMPtr<IWebUIDelegate> ui; if (SUCCEEDED(uiDelegate(&ui))) ui->webViewClose(this);}bool WebView::canHandleRequest(const WebCore::ResourceRequest& request){ // On the mac there's an about url protocol implementation but CFNetwork doesn't have that. if (equalIgnoringCase(String(request.url().protocol()), "about")) return true;#if USE(CFNETWORK) if (CFURLProtocolCanHandleRequest(request.cfURLRequest())) return true; // FIXME: Mac WebKit calls _representationExistsForURLScheme here return false;#else return true;#endif}String WebView::standardUserAgentWithApplicationName(const String& applicationName){ return String::format("Mozilla/5.0 (Windows; U; %s; %s) AppleWebKit/%s (KHTML, like Gecko)%s%s", osVersion().latin1().data(), defaultLanguage().latin1().data(), webKitVersion().latin1().data(), (applicationName.length() ? " " : ""), applicationName.latin1().data());}Page* WebView::page(){ return m_page;}bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam){ static const int contextMenuMargin = 1; // Translate the screen coordinates into window coordinates POINT coords = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; if (coords.x == -1 || coords.y == -1) { FrameView* view = m_page->mainFrame()->view(); if (!view) return false; int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT); IntPoint location; // The context menu event was generated from the keyboard, so show the context menu by the current selection. Position start = m_page->mainFrame()->selection()->selection().start(); Position end = m_page->mainFrame()->selection()->selection().end(); if (!start.node() || !end.node()) location = IntPoint(rightAligned ? view->contentsWidth() - contextMenuMargin : contextMenuMargin, contextMenuMargin); else { RenderObject* renderer = start.node()->renderer(); if (!renderer) return false; // Calculate the rect of the first line of the selection (cribbed from -[WebCoreFrameBridge firstRectForDOMRange:], // now Frame::firstRectForRange(), which perhaps this should call). int extraWidthToEndOfLine = 0; InlineBox* startInlineBox; int startCaretOffset; start.getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset); IntRect startCaretRect = renderer->localCaretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine); if (startCaretRect != IntRect()) startCaretRect = renderer->localToAbsoluteQuad(FloatRect(startCaretRect)).enclosingBoundingBox(); InlineBox* endInlineBox; int endCaretOffset; end.getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset); IntRect endCaretRect = renderer->localCaretRect(endInlineBox, endCaretOffset); if (endCaretRect != IntRect()) endCaretRect = renderer->localToAbsoluteQuad(FloatRect(endCaretRect)).enclosingBoundingBox(); IntRect firstRect; if (startCaretRect.y() == endCaretRect.y()) firstRect = IntRect(min(startCaretRect.x(), endCaretRect.x()), startCaretRect.y(), abs(endCaretRect.x() - startCaretRect.x()), max(startCaretRect.height(), endCaretRect.height())); else firstRect = IntRect(startCaretRect.x(), startCaretRect.y(), startCaretRect.width() + extraWidthToEndOfLine, startCaretRect.height()); location = IntPoint(rightAligned ? firstRect.right() : firstRect.x(), firstRect.bottom()); } location = view->contentsToWindow(location); // FIXME: The IntSize(0, -1) is a hack to get the hit-testing to result in the selected element. // Ideally we'd have the position of a context menu event be separate from its target node. coords = location + IntSize(0, -1); } else { if (!::ScreenToClient(m_viewWindow, &coords)) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -