iphoneからmacのマウスカーソルを操作 その2

先日は眠くて終わったので、少し詳細を書いておきます。

まず、iphoneからマウスを操作するって話ですが、イメージとしては以下のアプリみたいなものです。

MagicMouseが必要なくなる?iPhoneがワイヤレスマウスになる! – ツインズパパの徒然日記

AOSCの勉強会のとき、quo.jsの話と合わせて、こんなアプリもあるけどquo.jsで作れちゃうんじゃない?、みたいな話をしていました。

というわけで、ちょっとやってみました。
すばらしいライブラリばかりで本当に楽にプログラムを作れるようになったもんですね。

作り方

たいしたことはやっていないのですが、ポイントとしては3つ。

1.Mac上でマウスを操作するプログラムを作る。
2.Mac上でiphoneからのタッチ操作を受信するサーバーを作る。
3.iphoneブラウザでタッチ操作を取得してMacに送る。

一番よくわからなかったのは、Macのアプリを作る方法です。
初のXcodeでまだどうやってビルドするとかもよくわかっていません。。。

1.Mac上でマウスを操作するプログラムを作る。

まずは、よくわからないXCodeで作ります。
プロジェクトを作って適当にCで作ります。
マウスのポインタのxの増分とyの増分をもらって、その分マウスを移動するプログラムにします。

[c]
//
// main.c
// PostMouseEvent
//
// Created by Daisuke Igarashi on 2012/09/27.
// Copyright (c) 2012 Daisuke Igarashi. All rights reserved.
//

#include <CoreGraphics/CGEvent.h>
#include <CoreGraphics/CGEventTypes.h>
#include <CoreGraphics/CGDirectDisplay.h>
//#include <CoreGraphics/CGEventSource.h>
//#include <CoreGraphics/CGRemoteOperation.h>
#include
#include

void PostMouseEvent(CGMouseButton button, CGEventType type, const CGPoint point)
{
CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, point, button);
CGEventSetType(theEvent, type);
CGEventPost(kCGHIDEventTap, theEvent);
CFRelease(theEvent);
}

int main(int argc, const char * argv[])
{

if (argc != 3) {
return 1;
}

unsigned int width = (unsigned int)CGDisplayPixelsWide(kCGDirectMainDisplay);
unsigned int height = (unsigned int)CGDisplayPixelsHigh(kCGDirectMainDisplay);
CGPoint current_point = CGEventGetLocation(CGEventCreate(nil));

CGPoint point;
point.x = current_point.x + (CGFloat)(width * atof(argv[1]) / 100); // rate
point.y = current_point.y + (CGFloat)(height * atof(argv[2]) / 100);
CGMouseButton button = kCGMouseButtonLeft;
CGEventType type = kCGEventMouseMoved;

PostMouseEvent(button, type, point);

return 0;
}
[/c]

これをビルド・・・の仕方がわからないので、Runして生成されたアプリを探してきてコピペしました。
最初はリンクエラーでてたけど、一体どこで追加するかがわからず、そこが一番時間かかった気がします・・・。

2.Mac上でiphoneからのタッチ操作を受信するサーバーを作る。

ブラウザからデータを簡単に受信と言えばWebSocketということで、tornadoを使ってwebsocketサーバーを作ります。

ws_server.py
[python]
from __future__ import print_function
import os

import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.websocket

from tornado.options import define

define("port", default=8000, help="run on the given port", type=int)

class ControlMouseWebSocket(tornado.websocket.WebSocketHandler):
def open(self):
print(‘open’)

def on_message(self, message):
x, y = message.split(‘,’)
print(‘move to ‘, x, ‘,’, y)
os.system(‘bin/PostMouseEvent {x} {y}’.format(x=x, y=y))

def on_close(self):
print(‘close’)

class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/move", ControlMouseWebSocket),
]
settings = dict(
debug=True,
)
tornado.web.Application.__init__(self, handlers, **settings)

def main():
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(Application())
http_server.listen(8000)
tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
main()
[/python]

WebSocketでデータをもらって、1で作ったアプリに渡してあげます。
らくちん。

3.iphoneブラウザでタッチ操作を取得してMacに送る。

わざわざFlaskを使ってウェブサーバーを立てていますが、tornadoで返してもよさそうです。
Flaskのサーバーはいまのところはindex.htmlを返すだけです。

http_server.py
[python]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, render_template

def get_ipaddr():
”’かなり適当にIP取得・・・”’
import subprocess
ipaddr = ‘127.0.0.1’
lines = subprocess.check_output([‘ifconfig | grep -E "inets" | cut -d" " -f2’], shell=True)
for line in reversed(lines.split(‘n’)):
if line == ‘127.0.0.1’:
break
ipaddr = line
return ipaddr

wshost = get_ipaddr()

app = Flask(__name__)

@app.route(‘/’)
def index():
return render_template(‘index.html’, wshost=wshost)

if __name__ == ‘__main__’:
app.run(host="0.0.0.0", port=5000, debug=True)

[/python]

あとは、index.htmlでWebSocketに繋いで、タッチのイベントデータを送ってあげます。

index.html
[html]
var ws = new WebSocket("ws://{{ wshost }}:8000/move");

ws.onmessage = function(e) {

};

function sendPoint(x, y) {
ws.send(x + ‘,’ + y);
};
[/html]

全部のソースは planset/controlmouse · GitHub で。

現在のままだと、色々とダメなので暇なときに手を加えたいですね。

・マウスの移動しかできないのでせめてクリックできるようにしたい。
・画面の比率で移動量を渡しているので縦より横の方が沢山動くのでなおしたい。
・quo.jsを使ってスワイプとかピンチ操作もできたらいいなぁ
・py2exeみたいので、tornadoサーバーをmacアプリ化するライブラリがあればいいなぁ。
 更に、起動するとタスクバー?に格納するアプリにできればいい感じ。

まぁ、作っても使わないけどね!