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都差不多,不再赘述了。

 

你可能感兴趣的:(handler)