2

How do I get the position of the mouse pointer in ruby?

This should be the absolute (screen) position.

If this requires a system specific answer, I'm on Ubuntu.

Thanks

ZirconCode
  • 805
  • 2
  • 10
  • 24
  • You can use the gem *selenium-webdriver*. – Arup Rakshit Jun 30 '13 at 08:18
  • 4
    This question does not make sense unless the specific GUI system is specified. – sawa Jun 30 '13 at 08:23
  • 1
    http://stackoverflow.com/questions/8480073/how-would-i-get-the-current-mouse-coordinates-in-bash – Casper Jun 30 '13 at 10:47
  • Do you want the mouse coordinates in a web-browser? Or do you want them inside a window? If so: what kind of GUI library are you using? qt? gtk? visualruby? monkeybars? Please clarify. – nathanvda Jun 30 '13 at 15:24
  • 3
    i don't see the problem with this question, it is simple to me, the position of the mouse pointer in his OS – peter May 16 '14 at 14:49

1 Answers1

9

I assembled the following function. It does a dispatch on the operating system and follows a different strategy for each OS:

require 'rbconfig'

##
# Returns an array [x,y] containing the mouse coordinates
# Be aware that the coordinate system is OS dependent.
def getMouseLocation
  def windows
    require "Win32API"
    getCursorPos = Win32API.new("user32", "GetCursorPos", 'P', 'L')
    # point is a Long,Long-struct
    point = "\0" * 8
    if getCursorPos.Call(point)
      point.unpack('LL')
    else
      [nil,nil]
    end
  end

  def linux
    loc_string = `xdotool getmouselocation --shell`[/X=(\d+)\nY=(\d+)/]
    loc_string.lines.map {|s| s[/.=(\d+)/, 1].to_i}
  end

  def osx
    # if we are running in RubyCocoa, we can access objective-c libraries
    require "osx/cocoa"
    OSX::NSEvent.mouseLocation.to_a
  rescue LoadError
    # we are not running in ruby cocoa, but it should be preinstalled on every system
    coords = `/usr/bin/ruby -e 'require "osx/cocoa"; puts OSX::NSEvent.mouseLocation.to_a'`
    coords.lines.map {|s| s.to_f }
  end

  case RbConfig::CONFIG['host_os']
  when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
    windows
  when /darwin|mac os/
    osx
  when /linux|solaris|bsd/
    linux
  else
    raise Error, "unknown os: #{host_os.inspect}"
  end
rescue Exception => e
  [nil,nil]
end

Tested on Ubuntu 13.04 (gnome-shell), Windows 7 64bit, OS x 10.8.4 . I'd be glad, if someone could confirm that this works on other systems. A jruby solution is missing, too.

peter
  • 41,770
  • 5
  • 64
  • 108
tessi
  • 13,313
  • 3
  • 38
  • 50
  • I'm pretty sure this won't work on Windows. `xdotool` doesn't sound like something Windows would have. – John Dvorak Jun 30 '13 at 11:22
  • Right, I should have mentioned that windows is not supported. Do you know how to do this on windows? We could do some dispatch on the OS then. – tessi Jun 30 '13 at 11:25
  • `GetCursorPos` is the Windows equivalent: http://msdn.microsoft.com/en-us/library/ms648390%28VS.85%29.aspx – Chris Schmich Jun 30 '13 at 11:28
  • Thanks, I updated my answer to use `GetCursorPos` when running on windows – tessi Jun 30 '13 at 12:40
  • The [`Curses`](http://www.ruby-doc.org/stdlib-2.0/libdoc/curses/rdoc/Curses.html) module has `getmouse`, which "Returns coordinates of the mouse." That should be OS independent. – the Tin Man Jun 30 '13 at 15:59
  • The documentation sounds promising, even though I experience some weird behaviour when trying it in a IRB shell. – tessi Jun 30 '13 at 16:14
  • Don't run it in IRB. Run the Curses::MouseEvent example code stand-alone. IRB and such are already messing with the terminal to do their thing. – the Tin Man Jun 30 '13 at 16:26
  • 1
    Thanks, this is what I was looking for, sorry if my question was unclear. – ZirconCode Jul 01 '13 at 02:46
  • Updated to support OS X. Kudos goes to @meeee for guiding me. `Curses` seemed to work only on mouse-click (as it needs a mouse event). – tessi Jul 01 '13 at 07:12
  • Does not work in OS X 10.10.5 – Schroeder Sep 07 '16 at 19:34
  • Why don't you do `rescue Exception` rather than `rescue Exception => e`, since you're not using `e`? – Sapphire_Brick Jul 07 '20 at 19:11
  • no special reason really. my answer is a couple of years old so I can only guess why I did it back then- probably out of habit. – tessi Jul 12 '20 at 20:20