fingerpoken 0.2.20101209171641 → 0.2.20101216024109
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 +26 -7
- data/lib/fingerpoken/target.rb +6 -0
- data/lib/fingerpoken/tivo.rb +95 -0
- data/lib/fingerpoken/vnc.rb +2 -3
- data/lib/fingerpoken/xdo.rb +1 -1
- data/public/images/ajax-loader.png +0 -0
- data/public/images/form-check-off.png +0 -0
- data/public/images/form-check-on.png +0 -0
- data/public/images/form-radio-off.png +0 -0
- data/public/images/form-radio-on.png +0 -0
- data/public/images/icon-search-black.png +0 -0
- data/public/images/icons-18-black.png +0 -0
- data/public/images/icons-18-white.png +0 -0
- data/public/images/icons-36-black.png +0 -0
- data/public/images/icons-36-white.png +0 -0
- data/public/js/fingerpoken.js +132 -39
- data/views/index.haml +28 -3
- data/views/style.sass +2 -22
- metadata +15 -4
data/bin/fingerpoken.rb
CHANGED
@@ -26,19 +26,38 @@ class FingerPoken < Sinatra::Base
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def main(args)
|
29
|
+
targets = []
|
29
30
|
opts = OptionParser.new do |opts|
|
31
|
+
opts.banner = "Usage: #{$0} [options]"
|
32
|
+
|
33
|
+
opts.on("-t TARGET", "--target TARGET",
|
34
|
+
"Target a url. Can be given multiple times to target multiple things.") do |url|
|
35
|
+
target = URI.parse(url)
|
36
|
+
case target.scheme
|
37
|
+
when "xdo"
|
38
|
+
require "fingerpoken/#{target.scheme}"
|
39
|
+
targets << [:Xdo, {}]
|
40
|
+
when "vnc"
|
41
|
+
require "fingerpoken/#{target.scheme}"
|
42
|
+
targets << [:VNC, {}]
|
43
|
+
when "tivo"
|
44
|
+
require "fingerpoken/#{target.scheme}"
|
45
|
+
targets << [:Tivo, { :host => "192.168.0.134" }]
|
46
|
+
end
|
47
|
+
end
|
30
48
|
end
|
49
|
+
opts.parse(args)
|
50
|
+
|
51
|
+
puts targets
|
52
|
+
|
31
53
|
EventMachine::run do
|
32
54
|
$:.unshift(File.dirname(__FILE__) + "/lib")
|
33
55
|
channel = EventMachine::Channel.new
|
34
56
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#require "fingerpoken/vnc"
|
41
|
-
#target = FingerPoken::Target::VNC.new :channel => channel
|
57
|
+
targets.each do |klass, args|
|
58
|
+
args.merge!({ :channel => channel })
|
59
|
+
puts FingerPoken::Target.const_get(klass).new(args)
|
60
|
+
end
|
42
61
|
|
43
62
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 5001) do |ws|
|
44
63
|
ws.onmessage do |message|
|
data/lib/fingerpoken/target.rb
CHANGED
@@ -11,6 +11,8 @@ class FingerPoken::Target
|
|
11
11
|
case request["action"]
|
12
12
|
when "mousemove_relative"
|
13
13
|
mousemove_relative(request["rel_x"], request["rel_y"])
|
14
|
+
when "move_end"
|
15
|
+
move_end()
|
14
16
|
when "click"
|
15
17
|
click(request["button"])
|
16
18
|
when "mousedown"
|
@@ -60,4 +62,8 @@ class FingerPoken::Target
|
|
60
62
|
def keyup(key)
|
61
63
|
@logger.info("keyup not supported")
|
62
64
|
end
|
65
|
+
|
66
|
+
def move_end()
|
67
|
+
@logger.info("move_end not supported")
|
68
|
+
end
|
63
69
|
end # class FingerPoken::Target
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# TODO(sissel): Refactor the protocol into an EM::Tivo module.
|
4
|
+
|
5
|
+
require "rubygems"
|
6
|
+
require "fingerpoken/target"
|
7
|
+
require "ostruct"
|
8
|
+
|
9
|
+
class FingerPoken::Target::Tivo < FingerPoken::Target
|
10
|
+
def initialize(config)
|
11
|
+
super(config)
|
12
|
+
# TODO(sissel): Make this a config
|
13
|
+
@host = config[:host]
|
14
|
+
@tivo = EventMachine::connect(@host, 31339, TivoClient, self)
|
15
|
+
|
16
|
+
@state = OpenStruct.new # TODO(sissel): Make this not an open struct...
|
17
|
+
|
18
|
+
@state.speed = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def mousemove_relative(x, y)
|
22
|
+
direction = x < 0 ? -1 : 1
|
23
|
+
want_speed = [(x.abs / 30).to_i, 3].min
|
24
|
+
|
25
|
+
want_speed *= direction
|
26
|
+
if want_speed != @state.speed
|
27
|
+
p [want_speed]
|
28
|
+
end
|
29
|
+
|
30
|
+
if want_speed > @state.speed
|
31
|
+
# increase to it
|
32
|
+
1.upto(want_speed - @state.speed).each do
|
33
|
+
puts "UP"
|
34
|
+
@tivo.send_data("IRCODE FORWARD\r\n")
|
35
|
+
end
|
36
|
+
elsif (want_speed < @state.speed)
|
37
|
+
1.upto( (want_speed - @state.speed).abs ).each do
|
38
|
+
@tivo.send_data("IRCODE REVERSE\r\n")
|
39
|
+
puts "DOWN"
|
40
|
+
end
|
41
|
+
# decrease to it
|
42
|
+
end
|
43
|
+
@state.speed = want_speed
|
44
|
+
end
|
45
|
+
|
46
|
+
def move_end
|
47
|
+
@tivo.send_data("IRCODE PLAY\r\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
def click(button)
|
51
|
+
case button.to_i
|
52
|
+
when 1
|
53
|
+
@tivo.send_data("IRCODE PAUSE\r\n")
|
54
|
+
when 2 # 'middle' click (three fingers)
|
55
|
+
@tivo.send_data("IRCODE SELECT\r\n")
|
56
|
+
#when 2 # 'middle' click (three fingers)
|
57
|
+
#@tivo.send_data("IRCODE TIVO\r\n")
|
58
|
+
when 4 # scroll up
|
59
|
+
@tivo.send_data("IRCODE UP\r\n")
|
60
|
+
when 5 # scroll down
|
61
|
+
@tivo.send_data("IRCODE DOWN\r\n")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Hack for now
|
66
|
+
def keypress(key)
|
67
|
+
case key
|
68
|
+
when "Home"
|
69
|
+
@tivo.send_data("IRCODE TIVO\r\n")
|
70
|
+
when "Return"
|
71
|
+
@tivo.send_data("IRCODE SELECT\r\n")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class TivoClient < EventMachine::Connection
|
76
|
+
def initialize(target)
|
77
|
+
puts "init #{self} / #{target}"
|
78
|
+
@target = target
|
79
|
+
end
|
80
|
+
|
81
|
+
def connection_completed
|
82
|
+
@target.register
|
83
|
+
puts "Ready"
|
84
|
+
end
|
85
|
+
|
86
|
+
def receive_data(data)
|
87
|
+
p "Tivo says: #{data}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def send_data(data)
|
91
|
+
puts "Sending: #{data}"
|
92
|
+
super(data)
|
93
|
+
end
|
94
|
+
end # class TivoClient
|
95
|
+
end # class FingerPoken::Target::Tivo
|
data/lib/fingerpoken/vnc.rb
CHANGED
@@ -33,7 +33,6 @@ class FingerPoken::Target::VNC < FingerPoken::Target
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
36
|
def mousemove_relative(x, y)
|
38
37
|
@x += x
|
39
38
|
@y += y
|
@@ -41,14 +40,14 @@ class FingerPoken::Target::VNC < FingerPoken::Target
|
|
41
40
|
end
|
42
41
|
|
43
42
|
def mousedown(button)
|
44
|
-
button = (1 << (button - 1))
|
43
|
+
button = (1 << (button.to_i - 1))
|
45
44
|
return if @buttonmask & button != 0
|
46
45
|
@buttonmask |= button
|
47
46
|
update
|
48
47
|
end
|
49
48
|
|
50
49
|
def mouseup(button)
|
51
|
-
button = (1 << (button - 1))
|
50
|
+
button = (1 << (button.to_i - 1))
|
52
51
|
return if @buttonmask & button == 0
|
53
52
|
@buttonmask &= (~button)
|
54
53
|
update
|
data/lib/fingerpoken/xdo.rb
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/public/js/fingerpoken.js
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
/* TODO(sissel): This could use some serious refactoring. */
|
3
3
|
|
4
4
|
$(document).ready(function() {
|
5
|
+
var status = $("#status");
|
6
|
+
var config = function (key, value, default_value) {
|
7
|
+
if (value) {
|
8
|
+
status.html("config[" + key + "] = " + value);
|
9
|
+
//alert(key + " => " + value);
|
10
|
+
|
11
|
+
window.localStorage[key] = value
|
12
|
+
return value
|
13
|
+
} else {
|
14
|
+
return window.localStorage[key] || default_value
|
15
|
+
}
|
16
|
+
};
|
17
|
+
|
5
18
|
var state = {
|
6
19
|
x: -1,
|
7
20
|
y: -1,
|
@@ -10,8 +23,27 @@
|
|
10
23
|
width: window.innerWidth,
|
11
24
|
height: window.innerHeight,
|
12
25
|
key: undefined,
|
13
|
-
|
14
|
-
|
26
|
+
mouse: { },
|
27
|
+
scroll: {
|
28
|
+
y: 0,
|
29
|
+
}
|
30
|
+
};
|
31
|
+
|
32
|
+
/* Sync configuration elements */
|
33
|
+
|
34
|
+
/* Mouse movement */
|
35
|
+
console.log(config("fingerpoken/mouse/movement"));
|
36
|
+
$("input[name = \"mouse-config\"]")
|
37
|
+
.bind("change", function(event) {
|
38
|
+
config("fingerpoken/mouse/movement", event.target.value);
|
39
|
+
}).filter("[value = \"" + config("fingerpoken/mouse/movement") + "\"]")
|
40
|
+
.attr("checked", "checked").click()
|
41
|
+
|
42
|
+
$("input[name = \"mouse-acceleration\"]")
|
43
|
+
.bind("change", function(event) {
|
44
|
+
config("fingerpoken/mouse/acceleration", parseInt(event.target.value));
|
45
|
+
//status.html(event.target.value);
|
46
|
+
}).val(config("fingerpoken/mouse/acceleration")).change();
|
15
47
|
|
16
48
|
/* Changing orientation sometimes leaves the viewport
|
17
49
|
* not starting at 0,0. Fix it with this hack.
|
@@ -70,6 +102,8 @@
|
|
70
102
|
//});
|
71
103
|
|
72
104
|
|
105
|
+
/* TODO(sissel): add mousedown/mousemove/mouseup support */
|
106
|
+
console.log($("#touchpad-surface"));
|
73
107
|
$("#area").bind("touchstart", function(event) {
|
74
108
|
event.preventDefault();
|
75
109
|
var e = event.originalEvent;
|
@@ -95,9 +129,15 @@
|
|
95
129
|
}))
|
96
130
|
state.dragging = true;
|
97
131
|
}
|
98
|
-
}).bind("touchend", function(event) { /* $("#
|
132
|
+
}).bind("touchend", function(event) { /* $("#touchpadsurface").bind("touchend" ... */
|
99
133
|
var e = event.originalEvent;
|
100
134
|
var touches = e.touches;
|
135
|
+
|
136
|
+
if (state.mouse.vectorTimer) {
|
137
|
+
clearInterval(state.mouse.vectorTimer);
|
138
|
+
state.mouse.vectorTimer = null;
|
139
|
+
}
|
140
|
+
|
101
141
|
if (state.dragging) {
|
102
142
|
state.websocket.send(JSON.stringify({
|
103
143
|
action: "mouseup",
|
@@ -105,7 +145,7 @@
|
|
105
145
|
}));
|
106
146
|
state.dragging = false;
|
107
147
|
} else {
|
108
|
-
if (state.moving) {
|
148
|
+
if (state.moving && !state.scrolling) {
|
109
149
|
var e = state.last_move;
|
110
150
|
var r = e.rotation;
|
111
151
|
if (r < 0) {
|
@@ -114,7 +154,7 @@
|
|
114
154
|
|
115
155
|
status.html(r);
|
116
156
|
if (r > 75 && r < 105) {
|
117
|
-
/* Activate the keyboard when there's a 90-
|
157
|
+
/* Activate the keyboard when there's a ~90-degree rotation*/
|
118
158
|
var keyboard = $("<textarea id='keyboard' rows='10'></textarea>");
|
119
159
|
keyboard.css("width", "100%");
|
120
160
|
keyboard.css("height", "100%");
|
@@ -184,7 +224,14 @@
|
|
184
224
|
});
|
185
225
|
//status.html("<textarea id='keyboard'></textarea>");
|
186
226
|
//$("#keyboard").focus();
|
227
|
+
} else { /* Otherwise, we didn't rotate */
|
228
|
+
state.websocket.send(JSON.stringify({
|
229
|
+
action: "move_end",
|
230
|
+
now: (new Date()),
|
231
|
+
}));
|
187
232
|
}
|
233
|
+
} else if (state.scrolling) {
|
234
|
+
/* nothing for now */
|
188
235
|
} else {
|
189
236
|
/* No movement, click! */
|
190
237
|
status.html("Click!");
|
@@ -196,16 +243,17 @@
|
|
196
243
|
}
|
197
244
|
}
|
198
245
|
state.moving = false;
|
246
|
+
state.scrolling = false;
|
199
247
|
event.preventDefault();
|
200
|
-
}).bind("touchmove", function(event) { /* $("#
|
248
|
+
}).bind("touchmove", function(event) { /* $("#touchpadsurface").bind("touchmove" ... */
|
201
249
|
var e = event.originalEvent;
|
202
250
|
var touches = e.touches;
|
203
251
|
event.preventDefault();
|
204
252
|
if (!state.moving) {
|
205
253
|
/* Start calculating delta offsets now */
|
206
254
|
state.moving = true;
|
207
|
-
state.x = touches[0].clientX;
|
208
|
-
state.y = touches[0].clientY;
|
255
|
+
state.start_x = state.x = touches[0].clientX;
|
256
|
+
state.start_y = state.y = touches[0].clientY;
|
209
257
|
/* Skip this event */
|
210
258
|
return;
|
211
259
|
}
|
@@ -224,28 +272,33 @@
|
|
224
272
|
output += "rotation: " + r + "\n";
|
225
273
|
output += "scale: " + e.scale + "\n";
|
226
274
|
|
227
|
-
x = touches[0].clientX;
|
228
|
-
y = touches[0].clientY;
|
229
|
-
delta_x = (x - state.x);
|
230
|
-
delta_y = (y - state.y);
|
275
|
+
var x = touches[0].clientX;
|
276
|
+
var y = touches[0].clientY;
|
277
|
+
var delta_x = (x - state.x);
|
278
|
+
var delta_y = (y - state.y);
|
231
279
|
|
232
280
|
/* Apply acceleration */
|
233
|
-
sign_x = (delta_x < 0 ? -1 : 1);
|
234
|
-
sign_y = (delta_y < 0 ? -1 : 1);
|
235
|
-
delta_x = Math.ceil(Math.pow(Math.abs(delta_x), 1.5) * sign_x);
|
236
|
-
delta_y = Math.ceil(Math.pow(Math.abs(delta_y), 1.5) * sign_y);
|
281
|
+
var sign_x = (delta_x < 0 ? -1 : 1);
|
282
|
+
var sign_y = (delta_y < 0 ? -1 : 1);
|
237
283
|
|
284
|
+
/* jQuery Mobile or HTML 'range' inputs don't support floating point.
|
285
|
+
* Hack around it by using larger numbers and compensating. */
|
286
|
+
var accel = config("fingerpoken/mouse/acceleration", null, 150) / 100.0;
|
287
|
+
output += "Accel: " + accel + "\n";
|
238
288
|
|
289
|
+
var delta_x = Math.ceil(Math.pow(Math.abs(delta_x), accel) * sign_x);
|
290
|
+
var delta_y = Math.ceil(Math.pow(Math.abs(delta_y), accel) * sign_y);
|
239
291
|
output += "Delta: " + delta_x + ", " + delta_y + "\n";
|
240
|
-
status.html(output);
|
241
292
|
|
242
293
|
state.x = x;
|
243
294
|
state.y = y;
|
244
295
|
|
296
|
+
/* TODO(sissel): Make this a config option */
|
245
297
|
if (e.rotation < -10 || e.rotation > 10) {
|
246
298
|
/* Skip rotations that are probably not mouse-cursor-wanting movements */
|
247
299
|
return;
|
248
300
|
}
|
301
|
+
/* TODO(sissel): Make this a config option */
|
249
302
|
if (e.scale < 0.9 || e.scale > 1.1) {
|
250
303
|
/* Skip scales that are probably not mouse-cursor-wanting movements */
|
251
304
|
return;
|
@@ -253,22 +306,63 @@
|
|
253
306
|
|
254
307
|
if (touches.length > 1 && !state.dragging) {
|
255
308
|
/* Multifinger movement, probably should scroll? */
|
256
|
-
if (delta_y
|
309
|
+
if (Math.abs(delta_y) > 0) {
|
257
310
|
/* Scroll */
|
258
|
-
state.
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
311
|
+
state.scroll.y += delta_y;
|
312
|
+
|
313
|
+
/* Don't scroll every time we move, wait until we move enough
|
314
|
+
* that it is more than 10 pixels. */
|
315
|
+
/* TODO(sissel): Make this a config option */
|
316
|
+
if (Math.abs(state.scroll.y) > 10) {
|
317
|
+
state.scrolling = true;
|
318
|
+
state.moving = false;
|
319
|
+
state.scroll.y = 0;
|
320
|
+
state.websocket.send(JSON.stringify({
|
321
|
+
action: "click",
|
322
|
+
button: (delta_y < 0) ? 4 : 5,
|
323
|
+
}))
|
324
|
+
}
|
325
|
+
} /* if (Math.abs(delta_y) > 0) */
|
264
326
|
} else {
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
327
|
+
/* Only 1 finger, and we aren't dragging. So let's move! */
|
328
|
+
/* TODO(sissel): Refactor these in to fumctions */
|
329
|
+
var movement = config("fingerpoken/mouse/movement");
|
330
|
+
if (movement == "relative") {
|
331
|
+
status.html(output);
|
332
|
+
state.websocket.send(JSON.stringify({
|
333
|
+
action: "mousemove_relative",
|
334
|
+
rel_x: delta_x,
|
335
|
+
rel_y: delta_y
|
336
|
+
}));
|
337
|
+
} else if (movement == "vector") {
|
338
|
+
if (!state.mouse.vectorTimer) {
|
339
|
+
state.mouse.vectorTimer = setInterval(function() {
|
340
|
+
var rx = state.x - state.start_x;
|
341
|
+
var ry = state.y - state.start_y;
|
342
|
+
if (rx == 0 || ry == 0) {
|
343
|
+
return;
|
344
|
+
}
|
345
|
+
|
346
|
+
var sign_rx = (rx < 0 ? -1 : 1);
|
347
|
+
var sign_ry = (ry < 0 ? -1 : 1);
|
348
|
+
var vector_accel = accel / 1.7 /* feels like the right ratio */
|
349
|
+
|
350
|
+
output = "rx,ry = " + rx + ", " + ry + "\n";
|
351
|
+
rx = Math.ceil(Math.pow(Math.abs(rx), vector_accel) * sign_rx);
|
352
|
+
ry = Math.ceil(Math.pow(Math.abs(ry), vector_accel) * sign_ry);
|
353
|
+
output += "rx2,ry2 = " + rx + ", " + ry + "\n";
|
354
|
+
status.html(output)
|
355
|
+
|
356
|
+
state.websocket.send(JSON.stringify({
|
357
|
+
action: "mousemove_relative",
|
358
|
+
rel_x: rx,
|
359
|
+
rel_y: ry
|
360
|
+
}));
|
361
|
+
}, 15);
|
362
|
+
} /* if (!state.mouse.vectorTimer) */
|
363
|
+
} /* mouse vector movement */
|
364
|
+
} /* finger movement */
|
365
|
+
}); /* $("#touchpadsurface").bind( ... )*/
|
272
366
|
|
273
367
|
|
274
368
|
/* Take commands like this:
|
@@ -280,22 +374,21 @@
|
|
280
374
|
* <a class="command" data-action="click" data-button="button to click">
|
281
375
|
*/
|
282
376
|
$("a.command").bind("touchstart", function(event) {
|
283
|
-
//event.preventDefault();
|
284
377
|
state.touchelement = this;
|
285
|
-
}).bind("
|
378
|
+
}).bind("mousedown", function(event) {
|
379
|
+
state.touchelement = this;
|
380
|
+
event.preventDefault();
|
381
|
+
}).bind("touchmove mousemove", function(event) {
|
286
382
|
event.preventDefault();
|
287
|
-
}).bind("touchend", function(event) {
|
288
|
-
//event.preventDefault();
|
289
|
-
console.log(this)
|
383
|
+
}).bind("touchend mouseup", function(event) {
|
290
384
|
if (state.touchelement == this) {
|
291
|
-
console.log(this)
|
292
385
|
state.websocket.send(JSON.stringify({
|
293
386
|
action: $(this).attr("data-action"),
|
294
387
|
key: $(this).attr("data-key"),
|
295
|
-
button: $(this).attr("data-button"),
|
388
|
+
button: parseInt($(this).attr("data-button")),
|
296
389
|
}));
|
297
390
|
}
|
298
391
|
});
|
299
|
-
|
392
|
+
|
300
393
|
}); /* $(document).ready */
|
301
394
|
})();
|
data/views/index.haml
CHANGED
@@ -16,10 +16,11 @@
|
|
16
16
|
:type => "text/javascript" }
|
17
17
|
|
18
18
|
%body
|
19
|
+
/ touchpad
|
19
20
|
%div{"data-role" => "page", "data-theme" => "a", "id" => "touchpad"}
|
20
21
|
%div.header{"data-role" => "header"}
|
21
22
|
%h1 fingerpoken
|
22
|
-
%a{:href => "config", "data-role" => "button", "data-
|
23
|
+
%a{:href => "#config", "data-role" => "button", "data-rel" => "dialog", "data-transition" => "pop"} Config
|
23
24
|
%a{:href => "javascript:window.location.reload()", "data-role" => "button", "data-inline" => true} Reload
|
24
25
|
%div.content{"data-role" => "content"}
|
25
26
|
#area
|
@@ -27,7 +28,7 @@
|
|
27
28
|
|
28
29
|
%div.footer{"data-role" => "footer"}
|
29
30
|
%span.left
|
30
|
-
%a
|
31
|
+
%a{:href => "#commands", "data-role" => "button", "data-rel" => "dialog", "data-transition" => "pop"} Commands
|
31
32
|
%span.right
|
32
33
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "click", "data-button" => "1"} Left
|
33
34
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "click", "data-button" => "3"} Right
|
@@ -35,6 +36,7 @@
|
|
35
36
|
%div{"data-role" => "page", "data-theme" => "a", "id" => "commands"}
|
36
37
|
%div{"data-role" => "header"}
|
37
38
|
%h1 Commands
|
39
|
+
%a{:href => "#touchpad", "data-role" => "button"} Touchpad
|
38
40
|
%div{"data-role" => "content"}
|
39
41
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "Right"} Next Slide
|
40
42
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "Left"} Prev Slide
|
@@ -42,7 +44,30 @@
|
|
42
44
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "ctrl+plus"} Zoom In
|
43
45
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "ctrl+minus"} Zoom Out
|
44
46
|
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "ctrl+0"} Zoom Zero
|
45
|
-
|
47
|
+
%hr
|
48
|
+
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "alt+Return"} Full Screen
|
49
|
+
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "End"} End
|
50
|
+
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "Home"} Home
|
51
|
+
%a.command{:href => "#", "data-role" => "button", "data-action" => "keypress", "data-key" => "Return"} Return
|
52
|
+
|
53
|
+
%div{"data-role" => "page", "data-theme" => "a", "id" => "config"}
|
54
|
+
%div{"data-role" => "header"}
|
46
55
|
%a{:href => "#touchpad", "data-role" => "button"} Touchpad
|
56
|
+
%h1 Configuration
|
57
|
+
%div{"data-role" => "content"}
|
58
|
+
Mouse movement
|
59
|
+
|
60
|
+
/ Mouse movement type
|
61
|
+
%fieldset{"data-role" => "controlgroup"}
|
62
|
+
%input{:type => :radio, :name => "mouse-config", :id => "mouse-relative", :value => "relative"}
|
63
|
+
%label{:for => "mouse-relative"} relative
|
64
|
+
%input{:type => :radio, :name => "mouse-config", :id => "mouse-absolute", :value => "absolute"}
|
65
|
+
%label{:for => "mouse-absolute"} absolute
|
66
|
+
%input{:type => :radio, :name => "mouse-config", :id => "mouse-vector", :value => "vector"}
|
67
|
+
%label{:for => "mouse-vector"} vector
|
68
|
+
|
69
|
+
/ Mouse acceleration
|
70
|
+
%label{:for => "mouse-acceleration"} Acceleration
|
71
|
+
%input{:type => "range", :name => "mouse-acceleration", :id => "mouse-acceleration", :min => 1, :max => 300, :step => "any"}
|
47
72
|
|
48
73
|
%script{ :src => "/js/fingerpoken.js" }
|
data/views/style.sass
CHANGED
@@ -19,34 +19,14 @@ html, body
|
|
19
19
|
h1
|
20
20
|
color: orange
|
21
21
|
|
22
|
-
#menu
|
23
|
-
width: 100%
|
24
|
-
color: white
|
25
|
-
font-family: sans-serif
|
26
|
-
font-weight: bold
|
27
|
-
text-align: center
|
28
|
-
vertical-align: middle
|
29
|
-
padding: 0
|
30
|
-
padding-bottom: 5px
|
31
|
-
margin: 0
|
32
|
-
|
33
|
-
.item:last-child
|
34
|
-
border-right: 2px solid lightgreen
|
35
|
-
.item
|
36
|
-
font-size: 250%
|
37
|
-
border: 2px solid lightgreen
|
38
|
-
border-right: 0px
|
39
|
-
height: 40px
|
40
|
-
padding: 10px
|
41
|
-
margin: 0
|
42
|
-
text-align: center
|
43
|
-
vertical-align: middle
|
44
22
|
.content
|
45
23
|
.header
|
46
24
|
.footer
|
47
25
|
font-size: 120%
|
48
26
|
.right
|
49
27
|
float: right
|
28
|
+
//.content > #area
|
29
|
+
//padding: 0px !important
|
50
30
|
#area
|
51
31
|
width: 100%
|
52
32
|
height: 100%
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fingerpoken
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 40202432048205
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 20101216024109
|
10
|
+
version: 0.2.20101216024109
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jordan Sissel
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-16 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -71,11 +71,22 @@ extra_rdoc_files: []
|
|
71
71
|
files:
|
72
72
|
- lib/fingerpoken/xdo.rb
|
73
73
|
- lib/fingerpoken/target.rb
|
74
|
+
- lib/fingerpoken/tivo.rb
|
74
75
|
- lib/fingerpoken/vnc.rb
|
75
76
|
- public/reset.css
|
76
77
|
- public/js/fingerpoken.js
|
77
78
|
- public/js/jquery.min.js
|
78
79
|
- public/js/jquery.mobile-1.0a2.min.js
|
80
|
+
- public/images/form-radio-on.png
|
81
|
+
- public/images/form-check-on.png
|
82
|
+
- public/images/icons-36-white.png
|
83
|
+
- public/images/icons-36-black.png
|
84
|
+
- public/images/icon-search-black.png
|
85
|
+
- public/images/icons-18-white.png
|
86
|
+
- public/images/ajax-loader.png
|
87
|
+
- public/images/form-radio-off.png
|
88
|
+
- public/images/icons-18-black.png
|
89
|
+
- public/images/form-check-off.png
|
79
90
|
- public/jquery.mobile-1.0a2.min.css
|
80
91
|
- views/style.sass
|
81
92
|
- views/index.haml
|