zoukankan      html  css  js  c++  java
  • iOS WebCore的WebEvent和EventHandler

    WebEvent是iOS专有的类,负责封装和携带从UIKit得到的系统事件信息,并由WebKit层的WAKResponder子类传递到WebCore的EventHandler。

    UIKit层的逻辑可参考《iOS私有API(三) UIWebView下的手势识别器gestureRecognizer》,WebKit层的相关类可参考《WebCore::Widget浅探》。

    开源码中WebEvent的声明为:

    typedef enum {
        WebEventMouseDown,
        WebEventMouseUp,
        WebEventMouseMoved,
        
        WebEventScrollWheel,
        
        WebEventKeyDown,
        WebEventKeyUp,
        
        WebEventTouchBegin,
        WebEventTouchChange,
        WebEventTouchEnd,
        WebEventTouchCancel
    } WebEventType;
    
    typedef enum {
        WebEventTouchPhaseBegan,
        WebEventTouchPhaseMoved,
        WebEventTouchPhaseStationary,
        WebEventTouchPhaseEnded,
        WebEventTouchPhaseCancelled
    } WebEventTouchPhaseType;
    
    // These enum values are copied directly from GSEvent for compatibility.
    typedef enum
    {
        WebEventFlagMaskAlphaShift = 0x00010000,
        WebEventFlagMaskShift      = 0x00020000,
        WebEventFlagMaskControl    = 0x00040000,
        WebEventFlagMaskAlternate  = 0x00080000,
        WebEventFlagMaskCommand    = 0x00100000,
    } WebEventFlagValues;
    typedef unsigned WebEventFlags;
    
    // These enum values are copied directly from GSEvent for compatibility.
    typedef enum
    {
        WebEventCharacterSetASCII           = 0,
        WebEventCharacterSetSymbol          = 1,
        WebEventCharacterSetDingbats        = 2,
        WebEventCharacterSetUnicode         = 253,
        WebEventCharacterSetFunctionKeys    = 254,
    } WebEventCharacterSet;
    
    @interface WebEvent : NSObject {
    @private
        WebEventType _type;
        CFTimeInterval _timestamp;
        
        CGPoint _locationInWindow;
        
        NSString *_characters;
        NSString *_charactersIgnoringModifiers;
        WebEventFlags _modifierFlags;
        BOOL _keyRepeating;
        BOOL _popupVariant;
        uint16_t _keyCode;
        BOOL _tabKey;
        WebEventCharacterSet _characterSet;
        
        float _deltaX;
        float _deltaY;
        
        unsigned _touchCount;
        NSArray *_touchLocations;
        NSArray *_touchIdentifiers;
        NSArray *_touchPhases;
        
        BOOL _isGesture;
        float _gestureScale;
        float _gestureRotation;
    }
    
    - (WebEvent *)initWithMouseEventType:(WebEventType)type
                               timeStamp:(CFTimeInterval)timeStamp
                                location:(CGPoint)point;
    
    - (WebEvent *)initWithScrollWheelEventWithTimeStamp:(CFTimeInterval)timeStamp
                                               location:(CGPoint)point
                                                  deltaX:(float)deltaX
                                                  deltaY:(float)deltaY;
    
    - (WebEvent *)initWithTouchEventType:(WebEventType)type
                               timeStamp:(CFTimeInterval)timeStamp
                                location:(CGPoint)point
                               modifiers:(WebEventFlags)modifiers
                              touchCount:(unsigned)touchCount
                          touchLocations:(NSArray *)touchLocations
                        touchIdentifiers:(NSArray *)touchIdentifiers
                             touchPhases:(NSArray *)touchPhases isGesture:(BOOL)isGesture
                            gestureScale:(float)gestureScale
                         gestureRotation:(float)gestureRotation;
    
    - (WebEvent *)initWithKeyEventType:(WebEventType)type
                             timeStamp:(CFTimeInterval)timeStamp
                            characters:(NSString *)characters
           charactersIgnoringModifiers:(NSString *)charactersIgnoringModifiers
                             modifiers:(WebEventFlags)modifiers
                           isRepeating:(BOOL)repeating
                        isPopupVariant:(BOOL)popupVariant
                               keyCode:(uint16_t)keyCode
                              isTabKey:(BOOL)tabKey
                          characterSet:(WebEventCharacterSet)characterSet;
    
    @property(nonatomic,readonly) WebEventType type;
    @property(nonatomic,readonly) CFTimeInterval timestamp;
    
    // Mouse
    @property(nonatomic,readonly) CGPoint locationInWindow;
    
    // Keyboard
    @property(nonatomic,readonly,retain) NSString *characters;
    @property(nonatomic,readonly,retain) NSString *charactersIgnoringModifiers;
    @property(nonatomic,readonly) WebEventFlags modifierFlags;
    @property(nonatomic,readonly,getter=isKeyRepeating) BOOL keyRepeating;
    @property(nonatomic,readonly,getter=isPopupVariant) BOOL popupVariant;
    @property(nonatomic,readonly) uint16_t keyCode;
    @property(nonatomic,readonly,getter=isTabKey) BOOL tabKey;
    @property(nonatomic,readonly) WebEventCharacterSet characterSet;
    
    // Scroll Wheel
    @property(nonatomic,readonly) float deltaX;
    @property(nonatomic,readonly) float deltaY;
    
    // Touch
    @property(nonatomic,readonly) unsigned touchCount;
    @property(nonatomic,readonly,retain) NSArray *touchLocations;
    @property(nonatomic,readonly,retain) NSArray *touchIdentifiers;
    @property(nonatomic,readonly,retain) NSArray *touchPhases;
    
    // Gesture
    @property(nonatomic,readonly) BOOL isGesture;
    @property(nonatomic,readonly) float gestureScale;
    @property(nonatomic,readonly) float gestureRotation;
    @end


    WebEvent封装了4种事件:鼠标(手指)、键盘、滚轮、触摸,主要通过属性WebEventType type来区分。

    鼠标事件主要由单击手势来触发,会产生mouseup,mousemove和mousedown事件。其中单击就是同一RunLoop内连贯的mousedown和mouseup,而mousemove是模拟事件,可触发mouseover消息。

    键盘事件发生在编辑框内,按下iOS虚拟键盘的按键就会触发。

    滚轮由双指平移手势触发,在输入框内有效。

    触摸特指JavaScript监听的touchstart、gesturestart等消息,由UIWebTouchEventsGestureRecognizer来计算。

    这些事件触发后,都会在主线程创建WebEvent,然后用GCD技术转到WebThread执行。


    开源码的EventHandler.h中有如下几行:

    #if PLATFORM(MAC) && defined(__OBJC__)
        void mouseDown(WebEvent *);
        void mouseUp(WebEvent *);
        void mouseMoved(WebEvent *);
        bool keyEvent(WebEvent *);
        bool wheelEvent(WebEvent *);
    
        void touchEvent(WebEvent *);
    
    
        static WebEvent *currentEvent();
    #endif

    使用xdb也能找到,可是在EventHandler的实现中却找不到,所以 Apple是没有完全公开iOS源码的


    另有一个PlatformEventFactoryIOS.h的文件有如下声明:

    class PlatformEventFactory {
    public:
        static PlatformMouseEvent createPlatformMouseEvent(WebEvent *);
        static PlatformWheelEvent createPlatformWheelEvent(WebEvent *);
        static PlatformKeyboardEvent createPlatformKeyboardEvent(WebEvent *);
        static PlatformTouchEvent createPlatformTouchEvent(WebEvent *);
    };

    这些函数的作用就是把Objective-C类封装的WebEvent转换成WebCore里C++的PlatformEvent。可以猜测,接受WebEvent型参数的EventHandler函数也就只是简单做这个工作,转换后再直接调用通用的函数就ok了。如:

        bool handleMousePressEvent(const PlatformMouseEvent&);
        bool handleMouseMoveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0, bool onlyUpdateScrollbars = false);
        bool handleMouseReleaseEvent(const PlatformMouseEvent&);
        bool handleWheelEvent(const PlatformWheelEvent&);
        void defaultWheelEventHandler(Node*, WheelEvent*);
    
    #if ENABLE(GESTURE_EVENTS)
        bool handleGestureEvent(const PlatformGestureEvent&);
        bool handleGestureTap(const PlatformGestureEvent&, Node* preTargetedNode = 0);
        bool handleGestureScrollUpdate(const PlatformGestureEvent&);
    #endif

    一个堆栈示例:

    Thread 4 WebThread, Queue : (null)
    #0	0x03385790 in WebCore::EventHandler::mouseMoved(WebCore::PlatformMouseEvent const&) ()
    #1	0x0338ae0f in WebCore::EventHandler::mouseMoved(WebEvent*) ()
    #2	0x02efd822 in -[WebHTMLView(WebPrivate) mouseMoved:] ()
    #3	0x03f6c6ac in -[WAKView _selfHandleEvent:] ()
    #4	0x03f6c603 in -[WAKView handleEvent:] ()
    #5	0x03f6f94d in -[WAKWindow sendEventSynchronously:] ()
    #6	0x03f6f75b in __23-[WAKWindow sendEvent:]_block_invoke ()
    #7	0x03f83fe2 in _WebThreadRun ()
    #8	0x03f83ee0 in WebThreadRun ()
    #9	0x03f6f71c in -[WAKWindow sendEvent:] ()
    #10	0x03f6fa0c in __46-[WAKWindow sendMouseMoveEvent:contentChange:]_block_invoke ()
    #11	0x03f83fe2 in _WebThreadRun ()
    #12	0x03f83ee0 in WebThreadRun ()
    #13	0x03f6f9d2 in -[WAKWindow sendMouseMoveEvent:contentChange:] ()
    #14	0x0023609d in __64-[UIWebDocumentView(Interaction) _sendMouseMoveAndAttemptClick:]_block_invoke ()
    #15	0x03f844ea in HandleRunSource ()
    #16	0x0226e33f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
    #17	0x0226dd95 in __CFRunLoopDoSources0 ()
    #18	0x0228b124 in __CFRunLoopRun ()
    #19	0x0228a59f in CFRunLoopRunSpecific ()
    #20	0x0228a3eb in CFRunLoopRunInMode ()
    #21	0x03f83c30 in RunWebThread(void*) ()
    #22	0x05a5c65c in _pthread_body ()
    #23	0x05a5c4e6 in _pthread_start ()

    其它的Event都差不多,不再赘述了。

  • 相关阅读:
    让Extjs EditorGridPanel 编辑时支持方向键
    开发WebApp之PC客户端
    windows下mysql忘记root密码的解决方法
    TortoiseSVN使用svn+ssh协议连接服务器时重复提示输入密码
    jQuery Mobile页面跳转后未加载外部JS原因分析及解决
    在CentOS中安装与配置SVN的方法
    设置VMWARE通过桥接方式使用主机无线网卡上网
    关于sp_executesql与exec执行动态sql的区别--转载RascallySnake
    TreeView 点击触发父节点、子节点的连锁反应选中与取消
    Winform客户端发布与升级:ClickOnce
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3143194.html
Copyright © 2011-2022 走看看