iphone模拟触屏 svn/ trunk/ KeyMouseRelay/ KeyMouseRelay.mm

/**
* Name: KeyMouseRelay
* Type: iPhone OS 2.x SpringBoard extension (MobileSubstrate-based)
* Description: Extension to allow sending keyboard/mouse events to SpringBoard
* from an external application
* Author: Lance Fetters (aka. ashikase)
* Last-modified: 2009-02-23 19:41:21
*/
 
/**
* Copyright (C) 2009 Lance Fetters (aka. ashikase)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
 
#import "KeyMouseRelay.h"
 
#include <substrate.h>
#include <mach/mach_port.h>
#include <mach/mach_init.h>
 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#import <Foundation/Foundation.h>
 
#import <CoreGraphics/CGGeometry.h>
#import <GraphicsServices/GraphicsServices.h>
#import <QuartzCore/CAWindowServer.h>
#import <QuartzCore/CAWindowServerDisplay.h>
#import <SpringBoard/SpringBoard.h>
 
#define HOOK(class, name, type, args...) \
static type (*_ ## class ## $ ## name)(class *self, SEL sel, ## args); \
static type $ ## class ## $ ## name(class *self, SEL sel, ## args)
 
#define CALL_ORIG(class, name, args...) \
_ ## class ## $ ## name(self, sel, ## args)
 
//______________________________________________________________________________
//______________________________________________________________________________
 
// NOTE: The following two functions are modified from Jay Freeman (saurik)'s
// Veency
// http://svn.saurik.com/repos/menes/trunk/veency
 
static int buttons_ = 0;
static int x_ = 0, y_ = 0;
 
// WAS: void VNCPointer(int buttons, int x, int y, rfbClientPtr client)
static void relayMouse(int buttons, int x, int y)
{
x_ = x; y_ = y;
int diff = buttons_ ^ buttons;
bool twas((buttons_ & 0x1) != 0);
bool tis((buttons & 0x1) != 0);
buttons_ = buttons;
 
mach_port_t purple(0);
 
if ((diff & 0x10) != 0) {
struct GSEventRecord record;
 
memset(&record, 0, sizeof(record));
 
record.type = (buttons & 0x4) != 0 ?
GSEventTypeHeadsetButtonDown :
GSEventTypeHeadsetButtonUp;
 
record.timestamp = GSCurrentEventTimestamp();
 
GSSendSystemEvent(&record);
}
 
if ((diff & 0x04) != 0) {
struct GSEventRecord record;
 
memset(&record, 0, sizeof(record));
 
record.type = (buttons & 0x4) != 0 ?
GSEventTypeMenuButtonDown :
GSEventTypeMenuButtonUp;
 
record.timestamp = GSCurrentEventTimestamp();
 
GSSendSystemEvent(&record);
}
 
if ((diff & 0x02) != 0) {
struct GSEventRecord record;
 
memset(&record, 0, sizeof(record));
 
record.type = (buttons & 0x2) != 0 ?
GSEventTypeLockButtonDown :
GSEventTypeLockButtonUp;
 
record.timestamp = GSCurrentEventTimestamp();
 
GSSendSystemEvent(&record);
}
 
if (twas != tis || tis) {
struct {
struct GSEventRecord record;
struct {
struct GSEventRecordInfo info;
struct GSPathInfo path;
} data;
} event;
 
memset(&event, 0, sizeof(event));
 
event.record.type = GSEventTypeMouse;
event.record.locationInWindow.x = x;
event.record.locationInWindow.y = y;
event.record.timestamp = GSCurrentEventTimestamp();
event.record.size = sizeof(event.data);
 
event.data.info.handInfo.type = twas == tis ?
GSMouseEventTypeDragged :
tis ?
GSMouseEventTypeDown :
GSMouseEventTypeUp;
 
event.data.info.handInfo.x34 = 0x1;
event.data.info.handInfo.x38 = tis ? 0x1 : 0x0;
 
event.data.info.pathPositions = 1;
 
event.data.path.x00 = 0x01;
event.data.path.x01 = 0x02;
event.data.path.x02 = tis ? 0x03 : 0x00;
event.data.path.position = event.record.locationInWindow;
 
mach_port_t port(0);
 
if (CAWindowServer *server = [CAWindowServer serverIfRunning]) {
NSArray *displays([server displays]);
if (displays != nil && [displays count] != 0)
if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
port = [display clientPortAtPosition:event.record.locationInWindow];
}
 
if (port == 0) {
if (purple == 0)
purple = GSCopyPurpleSystemEventPort();
port = purple;
}
 
GSSendEvent(&event.record, port);
}
 
if (purple != 0)
mach_port_deallocate(mach_task_self(), purple);
}
 
// WAS: void VNCKeyboard(rfbBool down, rfbKeySym key, rfbClientPtr client)
static void relayKeyboard(unsigned short key)
{
if (key <= 0xfff) {
struct {
struct GSEventRecord record;
struct GSEventKeyInfo data;
} event;
 
memset(&event, 0, sizeof(event));
 
event.record.type = GSEventTypeKeyDown;
event.record.timestamp = GSCurrentEventTimestamp();
event.record.size = sizeof(event.data);
 
event.data.character = key;
 
mach_port_t port(0);
 
if (CAWindowServer *server = [CAWindowServer serverIfRunning]) {
NSArray *displays([server displays]);
if (displays != nil && [displays count] != 0)
if (CAWindowServerDisplay *display = [displays objectAtIndex:0])
//port = [display clientPortAtPosition:CGPointMake(x_, y_)];
port = [display clientPortAtPosition:CGPointMake(160, 240)];
}
 
if (port != 0)
GSSendEvent(&event.record, port);
}
}
 
//______________________________________________________________________________
//______________________________________________________________________________
 
// NOTE: The following two functions are modified from zataang's SpringBridge
// http://zataangstuff.googlecode.com/svn/trunk/SpringBridge/
 
static void relayDataCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
NSData *d = (NSData *)data;
if ([d length] == sizeof(KeyMouseEvent)) {
const KeyMouseEvent *event = reinterpret_cast<const KeyMouseEvent *>([d bytes]);
if (event->type == 0) {
// Key event
NSLog(@"KeyMouseRelay: received key press: %c", event->key);
relayKeyboard(event->key);
} else {
// Mouse event
NSLog(@"KeyMouseRelay: received mouse event at x:%d, y:%d, buttons:%d",
event->mouse.x, event->mouse.y, event->mouse.buttons);
relayMouse(event->mouse.buttons, event->mouse.x, event->mouse.y);
}
}
}
 
static void listenForRelayConnections()
{
CFSocketRef sock = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_DGRAM,
IPPROTO_UDP, kCFSocketDataCallBack, (CFSocketCallBack)&relayDataCallBack, NULL);
if (sock) {
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(KEYMOUSERELAY_PORT);
addr4.sin_addr.s_addr = inet_addr("127.0.0.1");
NSData *address4 = [NSData dataWithBytes:&addr4 length:sizeof(addr4)];
 
CFSocketError err;
if ((err = CFSocketSetAddress(sock, (CFDataRef)address4)) == kCFSocketSuccess) {
CFRunLoopRef cfrl = CFRunLoopGetCurrent();
CFRunLoopSourceRef source4 = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sock, 0);
CFRunLoopAddSource(cfrl, source4, kCFRunLoopCommonModes);
CFRelease(source4);
NSLog(@"KeyMouseRelay: Listening for connections on port: %d", KEYMOUSERELAY_PORT);
} else {
CFRelease(sock);
}
}
}
 
//______________________________________________________________________________
//______________________________________________________________________________
 
HOOK(SpringBoard, applicationDidFinishLaunching$, void, id app)
{
CALL_ORIG(SpringBoard, applicationDidFinishLaunching$, app);
listenForRelayConnections();
}
 
//______________________________________________________________________________
//______________________________________________________________________________
 
extern "C" void KeyMouseRelayInitialize()
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 
// NOTE: This library should only be loaded for SpringBoard
NSString *identifier = [[NSBundle mainBundle] bundleIdentifier];
if (![identifier isEqualToString:@"com.apple.springboard"])
return;
 
// Setup hooks
Class $SpringBoard(objc_getClass("SpringBoard"));
_SpringBoard$applicationDidFinishLaunching$ =
MSHookMessage($SpringBoard, @selector(applicationDidFinishLaunching:), &$SpringBoard$applicationDidFinishLaunching$);
 
[pool release];
}
 

/* vim: set syntax=objcpp sw=4 ts=4 sts=4 expandtab textwidth=80 ff=unix: */



http://code.google.com/p/iphone-tweaks/source/browse/trunk/KeyMouseRelay/KeyMouseRelay.mm

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值