WebKit事件派发

本文解析了WebKit在32位平台上如何处理设备事件、网络事件及定时器事件,并探讨了内部事件处理方式,提出统一事件处理架构的想法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/shunzi__1984/article/details/6192998

一般在一个网络应用系统中,都会一下几类事件: 网络事件, timer事件,以及设备事件,设备事件主要指鼠标,按键,以及paint等消息事件

webkit也不例外,小弟分析了一下32平台的实现,也无特殊之处

1. 设备事件

 设备事件仍然是通过win32平台的消息循环来派发,消息处理函数如下:

  1. LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  2. {  
  3.     LRESULT lResult = 0;  
  4.     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);  
  5.     WebView* webView = reinterpret_cast<WebView*>(longPtr);  
  6.     WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0;  
  7.     if (!mainFrameImpl || webView->isBeingDestroyed())  
  8.         return DefWindowProc(hWnd, message, wParam, lParam);  
  9.   
  10.     // hold a ref, since the WebView could go away in an event handler.  
  11.     COMPtr<WebView> protector(webView);  
  12.     ASSERT(webView);  
  13.   
  14.     // Windows Media Player has a modal message loop that will deliver messages  
  15.     // to us at inappropriate times and we will crash if we handle them when  
  16.     // they are delivered. We repost paint messages so that we eventually get  
  17.     // a chance to paint once the modal loop has exited, but other messages  
  18.     // aren't safe to repost, so we just drop them.  
  19.     if (PluginView::isCallingPlugin()) {  
  20.         if (message == WM_PAINT)  
  21.             PostMessage(hWnd, message, wParam, lParam);  
  22.         return 0;  
  23.     }  
  24.   
  25.     bool handled = true;  
  26.   
  27.     switch (message) {  
  28.         case WM_PAINT: {  
  29.             webView->paint(0, 0);  
  30.             break;  
  31.         }  
  32.         case WM_PRINTCLIENT:  
  33.             webView->paint((HDC)wParam, lParam);  
  34.             break;  
  35.         case WM_DESTROY:  
  36.             webView->setIsBeingDestroyed();  
  37.             webView->close();  
  38.             break;  
  39.         case WM_GESTURENOTIFY:  
  40.             handled = webView->gestureNotify(wParam, lParam);  
  41.             break;  
  42.         case WM_GESTURE:  
  43.             handled = webView->gesture(wParam, lParam);  
  44.             break;  
  45.         case WM_MOUSEMOVE:  
  46.         case WM_LBUTTONDOWN:  
  47.         case WM_MBUTTONDOWN:  
  48.         case WM_RBUTTONDOWN:  
  49.         case WM_LBUTTONDBLCLK:  
  50.         case WM_MBUTTONDBLCLK:  
  51.         case WM_RBUTTONDBLCLK:  
  52.         case WM_LBUTTONUP:  
  53.         case WM_MBUTTONUP:  
  54.         case WM_RBUTTONUP:  
  55.         case WM_MOUSELEAVE:  
  56.         case WM_CANCELMODE:  
  57.             if (Frame* coreFrame = core(mainFrameImpl))  
  58.                 if (coreFrame->view()->didFirstLayout())  
  59.                     handled = webView->handleMouseEvent(message, wParam, lParam);  
  60.             break;  
  61.         case WM_MOUSEWHEEL:  
  62.         case WM_VISTA_MOUSEHWHEEL:  
  63.             if (Frame* coreFrame = core(mainFrameImpl))  
  64.                 if (coreFrame->view()->didFirstLayout())  
  65.                     handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL);  
  66.             break;  
  67.         case WM_SYSKEYDOWN:  
  68.             handled = webView->keyDown(wParam, lParam, true);  
  69.             break;  
  70.         case WM_KEYDOWN:  
  71.             handled = webView->keyDown(wParam, lParam);  
  72.             break;  
  73.         case WM_SYSKEYUP:  
  74.             handled = webView->keyUp(wParam, lParam, true);  
  75.             break;  
  76.         case WM_KEYUP:  
  77.             handled = webView->keyUp(wParam, lParam);  
  78.             break;  
  79.         case WM_SYSCHAR:  
  80.             handled = webView->keyPress(wParam, lParam, true);  
  81.             break;  
  82.         case WM_CHAR:  
  83.             handled = webView->keyPress(wParam, lParam);  
  84.             break;  
  85.         // FIXME: We need to check WM_UNICHAR to support supplementary characters (that don't fit in 16 bits).  
  86.         case WM_SIZE:  
  87.             if (lParam != 0)  
  88.                 webView->sizeChanged(IntSize(LOWORD(lParam), HIWORD(lParam)));  
  89.             break;  
  90.         case WM_SHOWWINDOW:  
  91.             lResult = DefWindowProc(hWnd, message, wParam, lParam);  
  92.             if (wParam == 0) {  
  93.                 // The window is being hidden (e.g., because we switched tabs).  
  94.                 // Null out our backing store.  
  95.                 webView->deleteBackingStore();  
  96.             }  
  97. #if USE(ACCELERATED_COMPOSITING)  
  98.             else if (webView->isAcceleratedCompositing())  
  99.                 webView->layerRendererBecameVisible();  
  100. #endif  
  101.             break;  
  102.         case WM_SETFOCUS: {  
  103.             COMPtr<IWebUIDelegate> uiDelegate;  
  104.             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;  
  105.             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate  
  106.                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)  
  107.                 uiDelegatePrivate->webViewReceivedFocus(webView);  
  108.   
  109.             FocusController* focusController = webView->page()->focusController();  
  110.             if (Frame* frame = focusController->focusedFrame()) {  
  111.                 // Send focus events unless the previously focused window is a  
  112.                 // child of ours (for example a plugin).  
  113.                 if (!IsChild(hWnd, reinterpret_cast<HWND>(wParam)))  
  114.                     focusController->setFocused(true);  
  115.             } else  
  116.                 focusController->setFocused(true);  
  117.             break;  
  118.         }  
  119.         case WM_KILLFOCUS: {  
  120.             COMPtr<IWebUIDelegate> uiDelegate;  
  121.             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;  
  122.             HWND newFocusWnd = reinterpret_cast<HWND>(wParam);  
  123.             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate  
  124.                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate)  
  125.                 uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd);  
  126.   
  127.             FocusController* focusController = webView->page()->focusController();  
  128.             Frame* frame = focusController->focusedOrMainFrame();  
  129.             webView->resetIME(frame);  
  130.             // Send blur events unless we're losing focus to a child of ours.  
  131.             if (!IsChild(hWnd, newFocusWnd))  
  132.                 focusController->setFocused(false);  
  133.   
  134.             // If we are pan-scrolling when we lose focus, stop the pan scrolling.  
  135.             frame->eventHandler()->stopAutoscrollTimer();  
  136.   
  137.             break;  
  138.         }  
  139.         case WM_WINDOWPOSCHANGED:  
  140.             if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)  
  141.                 webView->updateActiveStateSoon();  
  142.             handled = false;  
  143.             break;  
  144.         case WM_CUT:  
  145.             webView->cut(0);  
  146.             break;  
  147.         case WM_COPY:  
  148.             webView->copy(0);  
  149.             break;  
  150.         case WM_PASTE:  
  151.             webView->paste(0);  
  152.             break;  
  153.         case WM_CLEAR:  
  154.             webView->delete_(0);  
  155.             break;  
  156.         case WM_COMMAND:  
  157.             if (HIWORD(wParam))  
  158.                 handled = webView->execCommand(wParam, lParam);  
  159.             else // If the high word of wParam is 0, the message is from a menu  
  160.                 webView->performContextMenuAction(wParam, lParam, false);  
  161.             break;  
  162.         case WM_MENUCOMMAND:  
  163.             webView->performContextMenuAction(wParam, lParam, true);  
  164.             break;  
  165.         case WM_CONTEXTMENU:  
  166.             handled = webView->handleContextMenuEvent(wParam, lParam);  
  167.             break;  
  168.         case WM_INITMENUPOPUP:  
  169.             handled = webView->onInitMenuPopup(wParam, lParam);  
  170.             break;  
  171.         case WM_MEASUREITEM:  
  172.             handled = webView->onMeasureItem(wParam, lParam);  
  173.             break;  
  174.         case WM_DRAWITEM:  
  175.             handled = webView->onDrawItem(wParam, lParam);  
  176.             break;  
  177.         case WM_UNINITMENUPOPUP:  
  178.             handled = webView->onUninitMenuPopup(wParam, lParam);  
  179.             break;  
  180.         case WM_XP_THEMECHANGED:  
  181.             if (Frame* coreFrame = core(mainFrameImpl)) {  
  182.                 webView->deleteBackingStore();  
  183.                 coreFrame->page()->theme()->themeChanged();  
  184.                 ScrollbarTheme::nativeTheme()->themeChanged();  
  185.                 RECT windowRect;  
  186.                 ::GetClientRect(hWnd, &windowRect);  
  187.                 ::InvalidateRect(hWnd, &windowRect, false);  
  188. #if USE(ACCELERATED_COMPOSITING)  
  189.                 if (webView->isAcceleratedCompositing())  
  190.                     webView->setRootLayerNeedsDisplay();  
  191. #endif  
  192.            }  
  193.             break;  
  194.         case WM_MOUSEACTIVATE:  
  195.             webView->setMouseActivated(true);  
  196.             handled = false;  
  197.             break;  
  198.         case WM_GETDLGCODE: {  
  199.             COMPtr<IWebUIDelegate> uiDelegate;  
  200.             COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate;  
  201.             LONG_PTR dlgCode = 0;  
  202.             UINT keyCode = 0;  
  203.             if (lParam) {  
  204.                 LPMSG lpMsg = (LPMSG)lParam;  
  205.                 if (lpMsg->message == WM_KEYDOWN)  
  206.                     keyCode = (UINT) lpMsg->wParam;  
  207.             }  
  208.             if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate  
  209.                 && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate  
  210.                 && SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode)))  
  211.                 return dlgCode;  
  212.             handled = false;  
  213.             break;  
  214.         }  
  215.         case WM_GETOBJECT:  
  216.             handled = webView->onGetObject(wParam, lParam, lResult);  
  217.             break;  
  218.         case WM_IME_STARTCOMPOSITION:  
  219.             handled = webView->onIMEStartComposition();  
  220.             break;  
  221.         case WM_IME_REQUEST:  
  222.             lResult = webView->onIMERequest(wParam, lParam);  
  223.             break;  
  224.         case WM_IME_COMPOSITION:  
  225.             handled = webView->onIMEComposition(lParam);  
  226.             break;  
  227.         case WM_IME_ENDCOMPOSITION:  
  228.             handled = webView->onIMEEndComposition();  
  229.             break;  
  230.         case WM_IME_CHAR:  
  231.             handled = webView->onIMEChar(wParam, lParam);  
  232.             break;  
  233.         case WM_IME_NOTIFY:  
  234.             handled = webView->onIMENotify(wParam, lParam, &lResult);  
  235.             break;  
  236.         case WM_IME_SELECT:  
  237.             handled = webView->onIMESelect(wParam, lParam);  
  238.             break;  
  239.         case WM_IME_SETCONTEXT:  
  240.             handled = webView->onIMESetContext(wParam, lParam);  
  241.             break;  
  242.         case WM_TIMER:  
  243.             switch (wParam) {  
  244.                 case UpdateActiveStateTimer:  
  245.                     KillTimer(hWnd, UpdateActiveStateTimer);  
  246.                     webView->updateActiveState();  
  247.                     break;  
  248.                 case DeleteBackingStoreTimer:  
  249.                     webView->deleteBackingStore();  
  250.                     break;  
  251.             }  
  252.             break;  
  253.         case WM_SETCURSOR:  
  254.             handled = ::SetCursor(webView->m_lastSetCursor);  
  255.             break;  
  256.         case WM_VSCROLL:  
  257.             handled = webView->verticalScroll(wParam, lParam);  
  258.             break;  
  259.         case WM_HSCROLL:  
  260.             handled = webView->horizontalScroll(wParam, lParam);  
  261.             break;  
  262.         default:  
  263.             handled = false;  
  264.             break;  
  265.     }  
  266.   
  267.     if (!handled)  
  268.         lResult = DefWindowProc(hWnd, message, wParam, lParam);  
  269.       
  270.     // Let the client know whether we consider this message handled.  
  271.     return (message == WM_KEYDOWN || message == WM_SYSKEYDOWN || message == WM_KEYUP || message == WM_SYSKEYUP) ? !handled : lResult;  
  272. }  

在32平台,webView仅仅需要实现消息处理函数,然后创建窗口,将其消息处理函数注册给目的窗口

 

2. 网络事件

 32平台是用的curl网络库,通过调用网络库的异步函数, webkit引擎与网络库的接口是ResouceHandler,发起网络请求,需要调用ResouceHandle::start(NetworkingContext* context),函数当网络事件到达,会调用如下函数:

  1. void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo)   
  2. {  
  3.     ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo));  
  4.     const UInt8* bytes = CFDataGetBytePtr(data);  
  5.     CFIndex length = CFDataGetLength(data);  
  6.   
  7.     LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->firstRequest().url().string().utf8().data());  
  8.   
  9.     if (handle->client())  
  10.         handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength);  
  11. }  

 

3.timer事件

timer事件的处理类似于设备事件,timer的平台初始化函数:

  1. static void initializeOffScreenTimerWindow()  
  2. {  
  3.     if (timerWindowHandle)  
  4.         return;  
  5.       
  6.     WNDCLASSEX wcex;  
  7.     memset(&wcex, 0, sizeof(WNDCLASSEX));  
  8.     wcex.cbSize = sizeof(WNDCLASSEX);  
  9.     wcex.lpfnWndProc    = TimerWindowWndProc;  
  10.     wcex.hInstance      = WebCore::instanceHandle();  
  11.     wcex.lpszClassName  = kTimerWindowClassName;  
  12.     RegisterClassEx(&wcex);  
  13.   
  14.     timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0,  
  15.        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, WebCore::instanceHandle(), 0);  
  16.     timerFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.TimerFired");  
  17. }  

timer的消息处理函数如下:

  1. LRESULT CALLBACK TimerWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  2. {  
  3. #if PLATFORM(WIN)  
  4.     // Windows Media Player has a modal message loop that will deliver messages  
  5.     // to us at inappropriate times and we will crash if we handle them when  
  6.     // they are delivered. We repost all messages so that we will get to handle  
  7.     // them once the modal loop exits.  
  8.     if (PluginView::isCallingPlugin()) {  
  9.         PostMessage(hWnd, message, wParam, lParam);  
  10.         return 0;  
  11.     }  
  12. #endif  
  13.   
  14.     if (message == timerFiredMessage) {  
  15.         InterlockedExchange(&pendingTimers, 0);  
  16.         processingCustomTimerMessage = true;  
  17.         sharedTimerFiredFunction();  
  18.         processingCustomTimerMessage = false;  
  19.     } else if (message == WM_TIMER) {  
  20.         if (wParam == sharedTimerID) {  
  21.             KillTimer(timerWindowHandle, sharedTimerID);  
  22.             sharedTimerFiredFunction();  
  23.         } else if (wParam == endHighResTimerID) {  
  24.             KillTimer(timerWindowHandle, endHighResTimerID);  
  25.             highResTimerActive = false;  
  26.             timeEndPeriod(timerResolution);  
  27.         }  
  28.     } else  
  29.         return DefWindowProc(hWnd, message, wParam, lParam);  
  30.   
  31.     return 0;  
  32. }  

引擎内部事件如何处理?

通过分析发现引擎内部的异步是通过timer来实现,具体请参照前面讲解timer的文章

 

通过上面的分析发现,webkit没有将事件的处理统一起来,如果在引擎中自己有一个事件的处理者,或者将以上事件的处理统一起来,其架构看起来会不会更加优美?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值