WebKit2 context menu hack
/* | |
コンテクストメニューの representedObject からリンク要素を得るサンプル | |
WebKit2.framework をリンクする必要がある。 | |
うまくリンクできない場合は WebKit2.framework を /Developer/SDKs/xx.sdk/System/Library/PrivateFrameworks | |
にコピーすればよさげ | |
正直 WKRelease() は正しく使えているか自信がない | |
*/ | |
enum Type { //from WebKit2/Shared/APIObject.h | |
TypeNull = 0, | |
TypeArray = 1, | |
TypeData = 7, | |
TypeDictionary = 8, | |
TypeString = 15, | |
TypeURL = 16 | |
} | |
extern void* WKRetain(void* type); | |
extern void WKRelease(void* type); | |
extern uint32_t WKGetTypeID(void* typeRef); | |
extern void* WKDictionaryGetItemForKey(void* dictionary, void* key); | |
extern void* WKStringCreateWithUTF8CString(const char* string); | |
extern size_t WKStringGetMaximumUTF8CStringSize(void* string); | |
extern size_t WKStringGetUTF8CString(void* string, char* buffer, size_t bufferSize); | |
extern void* WKURLCopyString(void* url); | |
NSString* htWKNSStringFromWKString(void* wkStr){ | |
if(!wkStr || WKGetTypeID(wkStr)!=TypeString)return nil; | |
size_t len=WKStringGetMaximumUTF8CStringSize(wkStr); | |
void* buf; | |
buf=malloc(len); | |
//終端のNULL付きです | |
len=WKStringGetUTF8CString(wkStr, buf, len); | |
NSString* keyStr=[[NSString alloc]initWithBytes:buf length:len-1 encoding:NSUTF8StringEncoding]; | |
free(buf); | |
return [keyStr autorelease]; | |
} | |
NSString* htWKNSStringFromWKURL(void* wkURL){ | |
if(!wkURL || WKGetTypeID(wkURL)!=TypeURL)return nil; | |
void* wkStr=WKURLCopyString(wkURL); | |
NSString* result=htWKNSStringFromWKString(wkStr); | |
WKRelease(wkStr); | |
return result; | |
} | |
//TypeString と TypeURL に対応。TypeURL の場合も NSString を返す | |
NSString* htWKDictionaryStringForKey(void*dic, NSString* key){ | |
void* wkStr=WKStringCreateWithUTF8CString([key cStringUsingEncoding:NSUTF8StringEncoding]); | |
void* val=WKDictionaryGetItemForKey(dic, wkStr); | |
WKRelease(wkStr); | |
if(val){ | |
uint32_t type=WKGetTypeID(val); | |
if(type==TypeString) return htWKNSStringFromWKString(val); | |
if(type==TypeURL) return htWKNSStringFromWKURL(val); | |
} | |
return nil; | |
} | |
// ここまでライブラリ的なやつ | |
// action の例 | |
/* | |
メニュー項目の action から呼ばれる | |
representedObject には「リンクをコピー」から横取りした WebUserDataWrapper を入れておく | |
WKDictionary には以下のキーが含まれている | |
"ImageURL", "IsLinkDataLocal", "LinkLabel", "CanHandleLinkURL", "ElementIsSelected", | |
"LinkURL", "AllowsFollowingLinkURL", "Frame", "LinkTitle", "SelectionString", "MediaURL" | |
*/ | |
-(void)copyLinkAndTitleMenuAction:(id)sender{ | |
id webUserDataWrapper=[sender representedObject]; | |
void* apiObject=[webUserDataWrapper userData]; //struct APIObject | |
uint32_t type=WKGetTypeID(apiObject); | |
if(type==TypeDictionary){ //8==TypeDictionary | |
NSString* linkStr=htWKDictionaryStringForKey(apiObject, @"LinkURL"); | |
NSString* titleStr=htWKDictionaryStringForKey(apiObject, @"LinkLabel"); | |
if(!linkStr)linkStr=@""; | |
if(!titleStr)titleStr=@""; | |
NSString* result=[NSString stringWithFormat:@"%@\n%@", titleStr, linkStr]; | |
NSPasteboard*pb=[NSPasteboard generalPasteboard]; | |
[pb clearContents]; | |
[pb setString:result forType:NSStringPboardType]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
WKStringGetUTF8CString() の返り値はヌル文字付き。NSStringを作るなら initWithBytes:length:encoding: で1バイト少なく指定するか initWithUTF8String: にそのまま渡すか