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

时间: 2024-10-31 07:32:12

iOS WebCore的WebEvent和EventHandler的相关文章

iOS WebCore的wak目录

<iOS的WebThread>中提到: iOS的WebCore开源码,6.1版本的下载地址为:http://opensource.apple.com/release/ios-61/ 比起webkit.org上的Mac开源码,会多了个wak目录,内有21个文件. 今天认真看了下全目录,还果然挖掘出好多信息.这21个文件的文件名,8个以WAK开头,6个以WebCoreThread开头,7个以WK开头. 一.WAK* 第一个文件WAKAppKitStubs.h里就有重大新闻,我一直的猜想都是正确的:

UIWebView体系结构(七)WebView

在<iOS WebCore的wak目录>中证实了iOS的WebKit是想尽可能复用Mac上的代码,所以WebView在iOS和Mac上差不多. Mac WebView的参考文档: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003822 当然,

iOS的WebThread

当用到UIWebView.UITextField.UITextView等类时,就会看到WebThread线程: 在lldb中搜索 (lldb) image lookup -r -s [wW]ebThread 会有超过一百个结果. 对于普通开发者而言,WebThread最有意义的东西恐怕是UIWebView的私有API - (void)_setDrawInWebThread:(BOOL)drawInWebThread; 设置YES后,会在WebThread进行渲染的某些操作(layoutTiles

IOS开发笔记

1 iphone开发笔记 2 3 退回输入键盘 4 - (BOOL) textFieldShouldReturn:(id)textField{ 5 [textField resignFirstResponder]; 6 } 7 8 CGRect 9 CGRect frame = CGRectMake (origin.x, origin.y, size.width, size.height):矩形 10 NSStringFromCGRect(someCG) 把CGRect结构转变为格式化字符串:

IDA反汇编/反编译静态分析iOS模拟器程序(三)函数表示与搜索函数

打开IDA一般都是去搜索函数,可以说函数是IDA工程的基本单位吧,数据结构什么的都是为函数服务而已.函数列表在界面左侧的Functions Window: 可以看到,UIKit有27789个函数呢.在搜索前要先知道函数的表示方式. Objective-C函数的表示: 拿UIView来做例子吧.在xcode documentation中,UIView的函数会有这样的表示: + (void)beginAnimations:(NSString *)animationID context:(void *

wcf-请问android/IOS如何使用WCF?

问题描述 请问android/IOS如何使用WCF? 如题,新手接触app发现无法直接操作数据库,之前都是做网站,看了一些帖子发现需要使用webserver 于是就做了一个wcf 心想调用起来应该不难,但是由于java基础不好 软件android studio导入jar 也找不到方法...ios更是一筹莫展,期望有具体点的方法,指导一下到底如何调用wcf 解决方案 wcf配置为支持http绑定 最好配置为使用soaphttp://www.cnblogs.com/iscode/archive/20

Summary of Critical and Exploitable iOS Vulnerabilities in 2016

Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong, Eakerqiu @ Team OverSky 0x00 Introduction iOS security is far more fragile than you believe. And there are lots of critical and exploitable iOS vuln

黑云压城城欲摧 - 2016年iOS公开可利用漏洞总结

黑云压城城欲摧 - 2016年iOS公开可利用漏洞总结 作者:蒸米,耀刺,黑雪 @ Team OverSky   0x00 序 iOS的安全性远比大家的想象中脆弱,除了没有公开的漏洞以外,还有很多已经公开并且可被利用的漏洞,本报告总结了2016年比较严重的iOS漏洞(可用于远程代码执行或越狱),希望能够对大家移动安全方面的工作和研究带来一些帮助. 0x01 iOS 10.1.1 公开的可利用漏洞 mach_portal攻击链:该攻击链是由Google Project Zero的Ian Beer公

iOS Safari阅读模式分析过程

本文为Safari阅读模式分析过程记录,没有做很好的整理.最终的输出见另一篇iOS Safari阅读模式研究. 1. Break on evaluate   b JSC::evaluate(JSC::ExecState*, JSC::ScopeChainNode*, JSC::SourceCode const&, JSC::JSValue, JSC::JSValue*)   dump the source content from JSC::SourceCode Printing descrip