x_do 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.project +17 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +27 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/lib/x_do.rb +13 -0
- data/lib/x_do/context.rb +101 -0
- data/lib/x_do/ffi_autogen.rb +37 -0
- data/lib/x_do/ffi_functions.rb +63 -0
- data/lib/x_do/ffi_lib.rb +45 -0
- data/lib/x_do/ffi_lib_ext.rb +62 -0
- data/lib/x_do/keyboard.rb +51 -0
- data/lib/x_do/mouse.rb +85 -0
- data/lib/x_do/window.rb +182 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/stdlib.rb +2 -0
- data/spec/x_do/context_spec.rb +127 -0
- data/spec/x_do/ffi_lib_ext_spec.rb +126 -0
- data/spec/x_do/keyboard_spec.rb +32 -0
- data/spec/x_do/mouse_spec.rb +53 -0
- data/spec/x_do/window_spec.rb +141 -0
- data/tasks/ffi_codegen.rb +108 -0
- metadata +252 -0
data/.document
ADDED
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'
|
data/lib/x_do/context.rb
ADDED
@@ -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
|
data/lib/x_do/ffi_lib.rb
ADDED
@@ -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
|