x_do 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.project ADDED
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>x_do</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>com.aptana.ruby.core.rubynature</nature>
16
+ </natures>
17
+ </projectDescription>
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+ # Add dependencies required to use your gem here.
3
+ gem 'ffi', '>= 1.0.0'
4
+
5
+ # Add dependencies to develop your gem here.
6
+ # Include everything needed to run rake, tests, features, etc.
7
+ group :development do
8
+ gem 'rspec', '~> 2.5.0'
9
+ gem 'bundler', '~> 1.0.0'
10
+ gem 'jeweler', '~> 1.5.2'
11
+ gem 'rcov', '>= 0'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ ffi (1.0.7)
6
+ rake (>= 0.8.7)
7
+ git (1.2.5)
8
+ jeweler (1.5.2)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+ rspec (2.5.0)
15
+ rspec-core (~> 2.5.0)
16
+ rspec-expectations (~> 2.5.0)
17
+ rspec-mocks (~> 2.5.0)
18
+ rspec-core (2.5.1)
19
+ rspec-expectations (2.5.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.5.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ ffi (>= 1.0.0)
29
+ jeweler (~> 1.5.2)
30
+ rcov
31
+ rspec (~> 2.5.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Victor Costan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,27 @@
1
+ = x_do
2
+
3
+ FFI ruby bindings for libxdo, which injects keystrokes and mouse events into X event queues.
4
+
5
+ == Installation
6
+
7
+ The gem requires libxdo on your machine to compile. On an Ubuntu system, you can get it by installing the libxdo-dev package.
8
+
9
+ == Testing
10
+
11
+ Tests require that xdotool is installed and on your path. On an Ubuntu system, you can get it by installing the xdotool package.
12
+
13
+ The terminal running the tests should remain focused while the suite runs, otherwise some tests will fail.
14
+
15
+ == Contributing to x_do
16
+
17
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
18
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
19
+ * Fork the project
20
+ * Start a feature/bugfix branch
21
+ * Commit and push until you are happy with your contribution
22
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
23
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
24
+
25
+ == Copyright
26
+
27
+ Copyright (c) 2011 Victor Costan. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts 'Run `bundle install` to install missing gems'
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = 'x_do'
16
+ gem.homepage = 'http://github.com/pwnall/x_do'
17
+ gem.license = 'MIT'
18
+ gem.summary = 'Ruby FFI for libxdo (X mouse / keypress injector)'
19
+ gem.description = 'Wraps libxdo using ffi, for high performance'
20
+ gem.email = 'victor@costan.us'
21
+ gem.authors = ['Victor Costan']
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ gem.add_runtime_dependency 'ffi', '>= 1.0.0'
25
+ gem.add_development_dependency 'rspec', '~> 2.5.0'
26
+ gem.add_development_dependency 'bundler', '~> 1.0.0'
27
+ gem.add_development_dependency 'jeweler', '~> 1.5.2'
28
+ gem.add_development_dependency 'rcov', '>= 0'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ require 'rspec/core'
33
+ require 'rspec/core/rake_task'
34
+ RSpec::Core::RakeTask.new(:spec) do |spec|
35
+ spec.pattern = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ spec.rcov = true
41
+ end
42
+
43
+ task :default => :spec
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ''
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "x_do #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
54
+
55
+ require 'tasks/ffi_codegen.rb'
56
+ task :package => :ffi_header
57
+ task :spec => :ffi_header
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/x_do.rb ADDED
@@ -0,0 +1,13 @@
1
+ # :nodoc: documented in x_do/context.rb
2
+ class XDo
3
+ end # namespace XDo
4
+
5
+ require 'x_do/context.rb'
6
+ require 'x_do/mouse.rb'
7
+ require 'x_do/keyboard.rb'
8
+ require 'x_do/window.rb'
9
+
10
+ require 'x_do/ffi_lib.rb'
11
+ require 'x_do/ffi_autogen.rb'
12
+ require 'x_do/ffi_functions.rb'
13
+ require 'x_do/ffi_lib_ext.rb'
@@ -0,0 +1,101 @@
1
+ # Context for automation actions.
2
+ class XDo
3
+ # Creates a context for an X display.
4
+ #
5
+ # Args:
6
+ # display_name:: an X display name, such as ":0"; if not given, libxdo will
7
+ # choose a default display (usually the one pointed by the
8
+ # DISPLAY variable)
9
+ def initialize(display_name = nil)
10
+ @_pointer = XDo::FFILib.xdo_new display_name
11
+ @_context = XDo::FFILib::XDoContext.new @_pointer
12
+ @keyboard = XDo::Keyboard.new self
13
+ @mouse = XDo::Mouse.new self
14
+ end
15
+
16
+ # Releases resources associated with this context.
17
+ def close
18
+ return unless @_context
19
+ XDo::FFILib.xdo_free @_pointer
20
+ @_pointer = nil
21
+ @_context = nil
22
+ end
23
+
24
+ # :nodoc: automatically close contexts as they go out of scope.
25
+ def finalize
26
+ close
27
+ end
28
+
29
+ # The display name for the current context.
30
+ def display_name
31
+ @_context[:display_name]
32
+ end
33
+
34
+ # The underlying libxdo context structure.
35
+ attr_accessor :_context
36
+ # Pointer to the underlying _libxdo context structure.
37
+ attr_accessor :_pointer
38
+
39
+ # The keyboard state for this context.
40
+ attr_accessor :keyboard
41
+
42
+ # The mouse state for this context.
43
+ attr_accessor :mouse
44
+
45
+ # Returns X windows matching a query.
46
+ #
47
+ # Args:
48
+ # options:: hash that accepts the following keys:
49
+ # :title:: grep pattern that the window title has to match
50
+ # :name:: grep pattern that the window name has to match
51
+ # :class:: grep pattern that the window class has to match
52
+ # :class_name:: grep pattern that the window class (name?) has to match
53
+ # :pid:: only return windows whose process ID equals this
54
+ # :screen:: only return windows in this screen number
55
+ # :visible:: if true, only visible windows will be returned
56
+ #
57
+ # Returns an array of Window instances that match the query.
58
+ def find_windows(options = {})
59
+ query = XDo::FFILib::XDoSearch.from_options options
60
+ windows_pointer = FFI::MemoryPointer.new :pointer, 1
61
+ count_pointer = FFI::MemoryPointer.new :ulong, 1
62
+ XDo::FFILib.xdo_window_search @_pointer, query, windows_pointer,
63
+ count_pointer
64
+ count = count_pointer.read_ulong
65
+ windows = windows_pointer.read_pointer.read_array_of_long(count)
66
+ windows.map { |window| XDo::Window.new self, window }
67
+ end
68
+
69
+ # Returns the currently active X window.
70
+ def active_window
71
+ window_pointer = FFI::MemoryPointer.new :ulong, 1
72
+ XDo::FFILib.xdo_window_get_active @_pointer, window_pointer
73
+ XDo::Window.new self, window_pointer.read_ulong
74
+ end
75
+
76
+ # Returns the X window that has the input focus.
77
+ def focused_window
78
+ window_pointer = FFI::MemoryPointer.new :ulong, 1
79
+ XDo::FFILib.xdo_window_get_focus @_pointer, window_pointer
80
+ XDo::Window.new self, window_pointer.read_ulong
81
+ end
82
+
83
+ # Returns the "real" X window that has the input focus.
84
+ #
85
+ # This calls xdo_window_sane_get_focus instead of xdo_window_get_focus and is
86
+ # recommended.
87
+ def real_focused_window
88
+ window_pointer = FFI::MemoryPointer.new :ulong, 1
89
+ XDo::FFILib.xdo_window_sane_get_focus @_pointer, window_pointer
90
+ XDo::Window.new self, window_pointer.read_ulong
91
+ end
92
+
93
+ # The version of the underlying library.
94
+ #
95
+ # This method is mostly useful as a health check on your installtion. A
96
+ # non-nil, non-empty result means the gem was built successfully against
97
+ # libxdo.
98
+ def self.lib_version
99
+ XDo::FFILib.xdo_version
100
+ end
101
+ end # class XDo
@@ -0,0 +1,37 @@
1
+ # Automatically generated by tasks/ffi_codegen.rb
2
+
3
+ # :nodoc: namespace
4
+ class XDo
5
+
6
+ # :nodoc: namespace
7
+ module FFILib
8
+ # Constant values extracted from headers.
9
+ module Consts
10
+ XDO_SUCCESS = 0
11
+ XDO_ERROR = 1
12
+ SEARCH_PID = 0x0008
13
+ SEARCH_ANY = nil
14
+ SEARCH_ALL = nil
15
+ SEARCH_TITLE = 0x0001
16
+ SEARCH_CLASS = 0x0002
17
+ SEARCH_NAME = 0x0004
18
+ SEARCH_SCREEN = 0x0020
19
+ SEARCH_CLASSNAME = 0x0040
20
+ SEARCH_ONLYVISIBLE = 0x0010
21
+ SIZE_USEHINTS = 1
22
+ SIZE_TO = 0
23
+ SIZE_FROM = 1
24
+ end # module XDo::FFILib::Consts
25
+
26
+ # Status returned by libxdo functions.
27
+ Status = enum [
28
+ :success, Consts::XDO_SUCCESS,
29
+ :error, Consts::XDO_ERROR,
30
+ ]
31
+
32
+ # Search directions.
33
+ Direction = enum [
34
+ ]
35
+
36
+ end # namespace XDo::FFILib
37
+ end # namespace XDo
@@ -0,0 +1,63 @@
1
+ require 'ffi'
2
+
3
+ # :nodoc: namespace
4
+ class XDo
5
+
6
+ # :nodoc: function attachments
7
+ module FFILib
8
+ attach_function :xdo_new, [:string], :pointer
9
+ attach_function :xdo_version, [], :string
10
+ attach_function :xdo_free, [:pointer], :void
11
+ attach_function :xdo_window_get_active, [:pointer, :pointer],
12
+ XDo::FFILib::Status
13
+ attach_function :xdo_window_get_focus, [:pointer, :pointer],
14
+ XDo::FFILib::Status
15
+ attach_function :xdo_window_sane_get_focus, [:pointer, :pointer],
16
+ XDo::FFILib::Status
17
+
18
+ attach_function :xdo_window_get_pid, [:pointer, :window], :int
19
+
20
+ attach_function :xdo_window_search, [:pointer, :pointer, :pointer, :pointer],
21
+ XDo::FFILib::Status
22
+
23
+ attach_function :xdo_window_activate, [:pointer, :window], XDo::FFILib::Status
24
+ attach_function :xdo_window_focus, [:pointer, :window], XDo::FFILib::Status
25
+ attach_function :xdo_window_raise, [:pointer, :window], XDo::FFILib::Status
26
+
27
+ attach_function :xdo_get_window_location, [:pointer, :window, :pointer,
28
+ :pointer, :pointer],
29
+ XDo::FFILib::Status
30
+ attach_function :xdo_get_window_size, [:pointer, :window, :pointer, :pointer],
31
+ XDo::FFILib::Status
32
+ attach_function :xdo_window_move, [:pointer, :window, :int, :int],
33
+ XDo::FFILib::Status
34
+ attach_function :xdo_window_setsize, [:pointer, :window, :int, :int, :int],
35
+ XDo::FFILib::Status
36
+ attach_function :xdo_mouselocation, [:pointer, :pointer, :pointer, :pointer],
37
+ XDo::FFILib::Status
38
+ attach_function :xdo_mousemove, [:pointer, :int, :int, :int],
39
+ XDo::FFILib::Status
40
+ attach_function :xdo_mousemove_relative, [:pointer, :int, :int],
41
+ XDo::FFILib::Status
42
+ attach_function :xdo_mouse_wait_for_move_from, [:pointer, :int, :int],
43
+ XDo::FFILib::Status
44
+ attach_function :xdo_mouse_wait_for_move_to, [:pointer, :int, :int],
45
+ XDo::FFILib::Status
46
+
47
+ attach_function :xdo_mousemove_relative_to_window, [:pointer, :window, :int,
48
+ :int], XDo::FFILib::Status
49
+ attach_function :xdo_mousedown, [:pointer, :window, :int], XDo::FFILib::Status
50
+ attach_function :xdo_mouseup, [:pointer, :window, :int], XDo::FFILib::Status
51
+ attach_function :xdo_click, [:pointer, :window, :int], XDo::FFILib::Status
52
+
53
+ attach_function :xdo_type, [:pointer, :window, :string, :int],
54
+ XDo::FFILib::Status
55
+ attach_function :xdo_keysequence, [:pointer, :window, :string, :int],
56
+ XDo::FFILib::Status
57
+ attach_function :xdo_keysequence_down, [:pointer, :window, :string, :int],
58
+ XDo::FFILib::Status
59
+ attach_function :xdo_keysequence_up, [:pointer, :window, :string, :int],
60
+ XDo::FFILib::Status
61
+ end # module XDo::FFILib
62
+
63
+ end # namespace XDo
@@ -0,0 +1,45 @@
1
+ require 'ffi'
2
+
3
+ # :nodoc: namespace
4
+ class XDo
5
+
6
+ # FFI to the raw libxdo functions.
7
+ module FFILib
8
+ extend FFI::Library
9
+ ffi_lib 'libxdo.so'
10
+
11
+ # :nodoc: lifted from xdo.h
12
+ class XDoContext < FFI::Struct
13
+ layout :xdpy, :pointer,
14
+ :display_name, :string,
15
+ :charcodes, :pointer,
16
+ :charcodes_len, :int,
17
+ :modmap, :pointer,
18
+ :keymap, :pointer,
19
+ :keycode_high, :int,
20
+ :keycode_low, :int,
21
+ :keysyms_per_keycode, :int,
22
+ :close_display_when_freed, :int
23
+ end # class XDo::FFILib::XDoContext
24
+
25
+ # :nodoc: lifted from xdo.h
26
+ class XDoSearch < FFI::Struct
27
+ layout :title, :pointer,
28
+ :winclass, :pointer,
29
+ :winclassname, :pointer,
30
+ :winname, :pointer,
31
+ :pid, :int,
32
+ :max_depth, :long,
33
+ :only_visible, :int,
34
+ :screen, :int,
35
+ :require, :int,
36
+ :searchmask, :int
37
+ end # class XDo::FFILib::XDoSearch
38
+
39
+ # :nodoc: Window from X11/X.h (Window -> XID -> unsigned long)
40
+ typedef :ulong, :window
41
+ # :nodoc: useconds_t from sys/types.h
42
+ typedef :ulong, :useconds_t
43
+ end # module XDo::FFILib
44
+
45
+ end # namespace XDo