Here's another code using rubycocoa you might try.
_rb_click({|:position|:{30, 10}, |:click|:1, |:restore|:true, |:prep|:false})
on _rb_click(desc)
(*
record desc : event descriptor record;
full spec = {|:position|:pos, |:click|:k, |:button|:b, |:flags|:m, |:restore|:r, |:prep|:p}
defaults = {|:position|:{}, |:click|:0, |:button|:1, |:flags|:"", |:restore|:false, |:prep|:true}
list pos : {x, y} or {}
number x, y = x, y global coordinate of position
{} denotes current location
integer k : click count (0, 1, 2 or 3}; 0 denotes only to move mouse and exit
integer b : button index (1 = left button, 2 = right button)
string m : modifier flags; e.g. 'ck' = control + command
a = capslock
s = shift
c = control
o = option
k = command
boolean r : true to restore original mouse location, false otherwise
boolean p : true to post preparatory left 1-click event to change UI context, false otherwise
return list : {x, y} = mouse location at exit
*)
considering numeric strings
if (system info)'s system version < "10.9" then
set ruby to "/usr/bin/ruby"
else
set ruby to "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby"
end if
end considering
set defaults to {|:position|:{}, |:click|:0, |:button|:1, |:flags|:"", |:restore|:false, |:prep|:true}
set {|:position|:pos, |:click|:k, |:button|:b, |:flags|:m, |:restore|:r, |:prep|:p} to desc & defaults
if pos = {} then
set {x, y} to {"%", "%"}
else
set {x, y} to pos
end if
if k is not in {0, 1, 2, 3} then error "invalid click count: " & k number 8000
if b is not in {1, 2} then error "invalid button index: " & b number 8000
if m = "" then set m to "%"
do shell script ruby & " <<'EOF' - " & x & " " & y & " " & k & " " & b & " " & m & " " & r & " " & p & "
require 'osx/cocoa'
include OSX
if ARGV[0..1] == ['%', '%']
pt = CGEventGetLocation(CGEventCreate(nil)) # current mouse location
else
pt = CGPoint.new
pt.x, pt.y = ARGV[0..1].map {|a| a.to_f}
end
clk, btn = ARGV[2..3].map {|a| a.to_i}
flg = ARGV[4]
res, prep = ARGV[5..6].map {|a| a == 'true'}
etype, mbtn = case btn
when 1 then [KCGEventLeftMouseDown, KCGMouseButtonLeft] # [1, 0]
when 2 then [KCGEventRightMouseDown, KCGMouseButtonRight] # [3, 1]
when 3 then [KCGEventOtherMouseDown, KCGMouseButtonCenter] # [25, 2]
else raise ArgumentError, %[invalid mouse button: #{btn}]
end
mtable = {
'a' => KCGEventFlagMaskAlphaShift,
's' => KCGEventFlagMaskShift,
'c' => KCGEventFlagMaskControl,
'o' => KCGEventFlagMaskAlternate,
'k' => KCGEventFlagMaskCommand,
}
mf = flg.split(//).inject(0) { |mf, x| (m = mtable[x]) ? mf | m : mf }
src = CGEventSourceCreate(KCGEventSourceStateHIDSystemState)
tap = KCGHIDEventTap
pt0 = CGEventGetLocation(CGEventCreate(src)) # current mouse location
# move mouse to target location
ev0 = CGEventCreateMouseEvent(src, KCGEventMouseMoved, pt, 0) # move mouse
CGEventPost(tap, ev0)
if clk == 0
puts pt.x, pt.y
exit
end
# post preparatory left mouse click to change UI context (optional)
if prep
ev1 = CGEventCreateMouseEvent(src, KCGEventLeftMouseDown, pt, KCGMouseButtonLeft) # mouse left button down
CGEventPost(tap, ev1)
CGEventSetType(ev1, KCGEventLeftMouseUp) # mouse left button up
CGEventPost(tap, ev1)
end
# post target mouse click(s) with given flags
ev = CGEventCreateMouseEvent(src, etype, pt, mbtn) # mouse button down
CGEventSetFlags(ev, mf) # set flags
CGEventSetIntegerValueField(ev, KCGMouseEventClickState, clk) # set click count
CGEventPost(tap, ev)
CGEventSetType(ev, etype + 1) # mouse button up
CGEventPost(tap, ev)
# restore mouse location (optional)
if res
CGEventSetLocation(ev0, pt0) # restore mouse location
CGEventPost(tap, ev0)
puts pt0.x, pt0.y
exit
end
puts pt.x, pt.y
EOF"
set rr to paragraphs of result
repeat with r in rr
set r's contents to r as number
end repeat
return rr
end _rb_click