fingerpoken 0.2.20101208032306
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/fingerpoken.rb +51 -0
- data/lib/fingerpoken/target.rb +59 -0
- data/lib/fingerpoken/vnc.rb +69 -0
- data/lib/fingerpoken/xdo.rb +78 -0
- metadata +112 -0
data/bin/fingerpoken.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "em-websocket"
|
5
|
+
require "json"
|
6
|
+
require "rack"
|
7
|
+
require "sinatra/async"
|
8
|
+
|
9
|
+
class FingerPoken < Sinatra::Base
|
10
|
+
register Sinatra::Async
|
11
|
+
set :haml, :format => :html5
|
12
|
+
set :logging, true
|
13
|
+
set :public, "#{File.dirname(__FILE__)}/../public"
|
14
|
+
set :views, "#{File.dirname(__FILE__)}/../views"
|
15
|
+
|
16
|
+
aget '/' do
|
17
|
+
headers "Content-Type" => "text/html"
|
18
|
+
body haml :index
|
19
|
+
end # GET /
|
20
|
+
|
21
|
+
aget '/style.css' do
|
22
|
+
headers "Content-Type" => "text/css; charset=utf8"
|
23
|
+
body sass :style
|
24
|
+
end # GET /style.css
|
25
|
+
end
|
26
|
+
|
27
|
+
EventMachine::run do
|
28
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
29
|
+
channel = EventMachine::Channel.new
|
30
|
+
|
31
|
+
# TODO(sissel): Pick up here and make command flags to choose the
|
32
|
+
# target (vnc, xdo, etc)
|
33
|
+
require "fingerpoken/xdo"
|
34
|
+
target = FingerPoken::Target::Xdo.new :channel => channel
|
35
|
+
|
36
|
+
#require "fingerpoken/vnc"
|
37
|
+
#target = FingerPoken::Target::VNC.new :channel => channel
|
38
|
+
|
39
|
+
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 5001) do |ws|
|
40
|
+
ws.onmessage do |message|
|
41
|
+
request = JSON.parse(message)
|
42
|
+
p request
|
43
|
+
channel.push(request)
|
44
|
+
end # ws.onmessage
|
45
|
+
end # WebSocket
|
46
|
+
|
47
|
+
Rack::Handler::Thin.run(
|
48
|
+
Rack::CommonLogger.new( \
|
49
|
+
Rack::ShowExceptions.new( \
|
50
|
+
FingerPoken.new)), :Port => 5000)
|
51
|
+
end # EventMachine::run
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
class FingerPoken::Target
|
4
|
+
def initialize(config)
|
5
|
+
@channel = config[:channel]
|
6
|
+
@logger = Logger.new(STDERR)
|
7
|
+
end
|
8
|
+
|
9
|
+
def register
|
10
|
+
@channel.subscribe do |request|
|
11
|
+
case request["action"]
|
12
|
+
when "mousemove_relative"
|
13
|
+
mousemove_relative(request["rel_x"], request["rel_y"])
|
14
|
+
when "click"
|
15
|
+
click(request["button"])
|
16
|
+
when "mousedown"
|
17
|
+
mousedown(request["button"])
|
18
|
+
when "mouseup"
|
19
|
+
mouseup(request["button"])
|
20
|
+
when "type"
|
21
|
+
type(request["string"])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Subclasses should implement this.
|
27
|
+
def mousemove_relative(x, y)
|
28
|
+
@logger.info("mousemove not supported")
|
29
|
+
end
|
30
|
+
|
31
|
+
def mousedown(button)
|
32
|
+
@logger.info("mousedown not supported")
|
33
|
+
end
|
34
|
+
|
35
|
+
def mouseup(button)
|
36
|
+
@logger.info("mouseup not supported")
|
37
|
+
end
|
38
|
+
|
39
|
+
def click(button)
|
40
|
+
mousedown(button)
|
41
|
+
mouseup(button)
|
42
|
+
end
|
43
|
+
|
44
|
+
def type(string)
|
45
|
+
@logger.info("typing not supported")
|
46
|
+
end
|
47
|
+
|
48
|
+
def keypress(key)
|
49
|
+
@logger.info("keypress not supported")
|
50
|
+
end
|
51
|
+
|
52
|
+
def keydown(key)
|
53
|
+
@logger.info("keydown not supported")
|
54
|
+
end
|
55
|
+
|
56
|
+
def keyup(key)
|
57
|
+
@logger.info("keyup not supported")
|
58
|
+
end
|
59
|
+
end # class FingerPoken::Target
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "eventmachine-vnc"
|
3
|
+
require "fingerpoken/target"
|
4
|
+
|
5
|
+
class FingerPoken::Target::VNC < FingerPoken::Target
|
6
|
+
attr_accessor :x
|
7
|
+
attr_accessor :y
|
8
|
+
attr_accessor :buttonmask
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
super(config)
|
12
|
+
# TODO(sissel): Make this configurable
|
13
|
+
@password = ENV["VNCPASS"]
|
14
|
+
@host = "sadness"
|
15
|
+
@port = 5900
|
16
|
+
|
17
|
+
@vnc = EventMachine::connect(@host, @port, VNCClient, self)
|
18
|
+
@x = 0
|
19
|
+
@y = 0
|
20
|
+
@buttonmask = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def update
|
24
|
+
p [@x, @y, @buttonmask]
|
25
|
+
@vnc.pointerevent(@x, @y, @buttonmask)
|
26
|
+
|
27
|
+
# TODO(sissel): Hack to make it work in TF2.
|
28
|
+
# Mouse movement is always "from center"
|
29
|
+
# So after each move, center the cursor.
|
30
|
+
#@x = (@vnc.screen_width / 2).to_i
|
31
|
+
#@y = (@vnc.screen_height / 2).to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def mousemove_relative(x, y)
|
36
|
+
@x += x
|
37
|
+
@y += y
|
38
|
+
update
|
39
|
+
end
|
40
|
+
|
41
|
+
def mousedown(button)
|
42
|
+
button = (1 << (button - 1))
|
43
|
+
return if @buttonmask & button != 0
|
44
|
+
@buttonmask |= button
|
45
|
+
update
|
46
|
+
end
|
47
|
+
|
48
|
+
def mouseup(button)
|
49
|
+
button = (1 << (button - 1))
|
50
|
+
return if @buttonmask & button == 0
|
51
|
+
@buttonmask &= (~button)
|
52
|
+
update
|
53
|
+
end
|
54
|
+
|
55
|
+
class VNCClient < EventMachine::Connection
|
56
|
+
include EventMachine::Protocols::VNC::Client
|
57
|
+
|
58
|
+
def initialize(target)
|
59
|
+
@target = target
|
60
|
+
end
|
61
|
+
|
62
|
+
def ready
|
63
|
+
@target.register
|
64
|
+
@target.x = (@screen_width / 2).to_i
|
65
|
+
@target.y = (@screen_height / 2).to_i
|
66
|
+
@target.buttonmask = 0
|
67
|
+
end
|
68
|
+
end # class VNCClient
|
69
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "ffi"
|
5
|
+
require "fingerpoken/target"
|
6
|
+
|
7
|
+
class FingerPoken::Target::Xdo < FingerPoken::Target
|
8
|
+
module LibXdo
|
9
|
+
extend FFI::Library
|
10
|
+
ffi_lib "libxdo.so"
|
11
|
+
|
12
|
+
attach_function :xdo_new, [:string], :pointer
|
13
|
+
attach_function :xdo_mousemove, [:pointer, :int, :int, :int], :int
|
14
|
+
attach_function :xdo_mousemove_relative, [:pointer, :int, :int], :int
|
15
|
+
attach_function :xdo_click, [:pointer, :long, :int], :int
|
16
|
+
attach_function :xdo_mousedown, [:pointer, :long, :int], :int
|
17
|
+
attach_function :xdo_mouseup, [:pointer, :long, :int], :int
|
18
|
+
attach_function :xdo_type, [:pointer, :long, :string, :long], :int
|
19
|
+
attach_function :xdo_keysequence, [:pointer, :long, :string, :long], :int
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(config)
|
23
|
+
super(config)
|
24
|
+
@xdo = LibXdo::xdo_new(nil)
|
25
|
+
if @xdo.null?
|
26
|
+
raise "xdo_new failed"
|
27
|
+
end
|
28
|
+
register
|
29
|
+
end
|
30
|
+
|
31
|
+
def mousemove_relative(x, y)
|
32
|
+
@logger.info("move #{x},#{y}")
|
33
|
+
return LibXdo::xdo_mousemove_relative(@xdo, x, y)
|
34
|
+
end
|
35
|
+
|
36
|
+
def click(button)
|
37
|
+
LibXdo::xdo_click(@xdo, 0, button)
|
38
|
+
end
|
39
|
+
|
40
|
+
def mousedown(button)
|
41
|
+
LibXdo::xdo_mousedown(@xdo, 0, button)
|
42
|
+
end
|
43
|
+
|
44
|
+
def mouseup(button)
|
45
|
+
LibXdo::xdo_mouseup(@xdo, 0, button)
|
46
|
+
end
|
47
|
+
|
48
|
+
def type(string)
|
49
|
+
LibXdo::xdo_type(@xdo, 0, string, 12000)
|
50
|
+
end
|
51
|
+
|
52
|
+
def keypress(key)
|
53
|
+
key = request["key"]
|
54
|
+
if key.is_a?(String)
|
55
|
+
if key.length == 1
|
56
|
+
# Assume letter
|
57
|
+
LibXdo::xdo_type(@xdo, 0, key, 12000)
|
58
|
+
else
|
59
|
+
# Assume keysym
|
60
|
+
LibXdo::xdo_keysequence(@xdo, 0, key, 12000)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# type printables, key others.
|
64
|
+
if 32.upto(127).include?(key)
|
65
|
+
LibXdo::xdo_type(@xdo, 0, request["key"].chr, 12000)
|
66
|
+
else
|
67
|
+
case key
|
68
|
+
when 8
|
69
|
+
LibXdo::xdo_keysequence(@xdo, 0, "BackSpace", 12000)
|
70
|
+
when 13
|
71
|
+
LibXdo::xdo_keysequence(@xdo, 0, "Return", 12000)
|
72
|
+
else
|
73
|
+
puts "I don't know how to type web keycode '#{key}'"
|
74
|
+
end # case key
|
75
|
+
end # if 32.upto(127).include?(key)
|
76
|
+
end # if key.is_a?String
|
77
|
+
end # def keypress
|
78
|
+
end # class FingerPoken::Target::Xdo
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fingerpoken
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 40202416064627
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 20101208032306
|
10
|
+
version: 0.2.20101208032306
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jordan Sissel
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-08 00:00:00 -08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: eventmachine-vnc
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: ffi
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: eventmachine
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
description: fingerpoken - turns your ipad/itouch/iphone into a remote touchpad, keyboard, etc
|
64
|
+
email: jls@semicomplete.com
|
65
|
+
executables:
|
66
|
+
- fingerpoken.rb
|
67
|
+
extensions: []
|
68
|
+
|
69
|
+
extra_rdoc_files: []
|
70
|
+
|
71
|
+
files:
|
72
|
+
- lib/fingerpoken/xdo.rb
|
73
|
+
- lib/fingerpoken/target.rb
|
74
|
+
- lib/fingerpoken/vnc.rb
|
75
|
+
- bin/fingerpoken.rb
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: https://github.com/jordansissel/eventmachine-vnc
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
requirements: []
|
105
|
+
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.3.7
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: fingerpoken - turns your ipad/itouch/iphone into a remote touchpad, keyboard, etc
|
111
|
+
test_files: []
|
112
|
+
|