x_do 0.1.0
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/.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
@@ -0,0 +1,62 @@
|
|
1
|
+
# Extensions to the structures in ffi_lib.
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
class XDo
|
5
|
+
|
6
|
+
# :nodoc: namespace
|
7
|
+
module FFILib
|
8
|
+
|
9
|
+
# :nodoc: extending with better constructor
|
10
|
+
class XDoSearch
|
11
|
+
# Creates an XDoSearch structure from options passed to XDo#find_window.
|
12
|
+
def self.from_options(options = {})
|
13
|
+
search = self.new
|
14
|
+
search[:max_depth] = (options[:depth] || -1).to_i
|
15
|
+
|
16
|
+
# SEARCH_ANY vs SEARCH_ALL in xdo.h
|
17
|
+
search[:require] = (options[:require] == :any) ? 0 : 1
|
18
|
+
|
19
|
+
search[:searchmask] = 0
|
20
|
+
[
|
21
|
+
[:title, :title, XDo::FFILib::Consts::SEARCH_TITLE],
|
22
|
+
[:name, :winname, XDo::FFILib::Consts::SEARCH_NAME],
|
23
|
+
[:class, :winclass, XDo::FFILib::Consts::SEARCH_CLASS],
|
24
|
+
[:class_name, :winclassname, XDo::FFILib::Consts::SEARCH_CLASSNAME]
|
25
|
+
].each do |option, struct_key, bit|
|
26
|
+
if options[option]
|
27
|
+
search[:searchmask] |= bit
|
28
|
+
|
29
|
+
c_string = FFI::MemoryPointer.new options[option].length + 1
|
30
|
+
c_string.put_string 0, options[option]
|
31
|
+
search[struct_key] = c_string
|
32
|
+
else
|
33
|
+
search[struct_key] = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if options[:visible]
|
38
|
+
search[:searchmask] |= XDo::FFILib::Consts::SEARCH_ONLYVISIBLE
|
39
|
+
search[:only_visible] = 1
|
40
|
+
else
|
41
|
+
search[:only_visible] = 0
|
42
|
+
end
|
43
|
+
|
44
|
+
[
|
45
|
+
[:pid, :pid, XDo::FFILib::Consts::SEARCH_PID],
|
46
|
+
[:screen, :screen, XDo::FFILib::Consts::SEARCH_SCREEN]
|
47
|
+
].each do |option, struct_key, bit|
|
48
|
+
if options[option]
|
49
|
+
search[:searchmask] |= bit
|
50
|
+
search[struct_key] = options[option].to_i
|
51
|
+
else
|
52
|
+
search[struct_key] = 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
search
|
57
|
+
end
|
58
|
+
end # class XDo::FFILib::XDoSearch
|
59
|
+
|
60
|
+
end # module XDo::FFILib
|
61
|
+
|
62
|
+
end # namespace XDo
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
class XDo
|
3
|
+
|
4
|
+
# The keyboard state for a libxdo context.
|
5
|
+
class Keyboard
|
6
|
+
# Creates a keyboard state wrapper for an XDo context.
|
7
|
+
#
|
8
|
+
# This constructor is called internally by XDo#keyboard and client code
|
9
|
+
# should not need to call it directly.
|
10
|
+
#
|
11
|
+
# Args:
|
12
|
+
# xdo:: the XDo wrapping a libxdo context
|
13
|
+
def initialize(xdo)
|
14
|
+
@xdo = xdo
|
15
|
+
@_xdo_pointer = xdo._pointer
|
16
|
+
end
|
17
|
+
|
18
|
+
# The XDo context that produced the window.
|
19
|
+
attr_accessor :xdo
|
20
|
+
|
21
|
+
# Types a string into the current window.
|
22
|
+
def type_string(string, delay = 0.12)
|
23
|
+
XDo::FFILib.xdo_type @_xdo_pointer, 0, string, (delay * 100_000).to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
# Sends a keysequence to this window.
|
27
|
+
#
|
28
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
29
|
+
def type_keysequence(keysequence, delay = 0.12)
|
30
|
+
XDo::FFILib.xdo_keysequence @_xdo_pointer, 0, keysequence,
|
31
|
+
(delay * 100_000).to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
# Presses a keysequence in this window.
|
35
|
+
#
|
36
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
37
|
+
def press_keysequence(keysequence, delay = 0.12)
|
38
|
+
XDo::FFILib.xdo_keysequence_down @_xdo_pointer, 0, keysequence,
|
39
|
+
(delay * 100_000).to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
# Releases a keysequence in this window.
|
43
|
+
#
|
44
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
45
|
+
def release_keysequence(keysequence, delay = 0.12)
|
46
|
+
XDo::FFILib.xdo_keysequence_up @_xdo_pointer, 0, keysequence,
|
47
|
+
(delay * 100_000).to_i
|
48
|
+
end
|
49
|
+
end # class XDo::Keyboard
|
50
|
+
|
51
|
+
end # namespace XDo
|
data/lib/x_do/mouse.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
class XDo
|
3
|
+
|
4
|
+
# The mouse state for a libxdo context.
|
5
|
+
class Mouse
|
6
|
+
# Creates a mouse state wrapper for an XDo context.
|
7
|
+
#
|
8
|
+
# This constructor is called internally by XDo#mouse and client code
|
9
|
+
# should not need to call it directly.
|
10
|
+
#
|
11
|
+
# Args:
|
12
|
+
# xdo:: the XDo wrapping a libxdo context
|
13
|
+
def initialize(xdo)
|
14
|
+
@xdo = xdo
|
15
|
+
@_xdo_pointer = xdo._pointer
|
16
|
+
end
|
17
|
+
|
18
|
+
# The XDo context that produced the window.
|
19
|
+
attr_accessor :xdo
|
20
|
+
|
21
|
+
# [x, y, screen] array of mouse coordinates.
|
22
|
+
def location
|
23
|
+
x_pointer = FFI::MemoryPointer.new :int, 1
|
24
|
+
y_pointer = FFI::MemoryPointer.new :int, 1
|
25
|
+
screen_pointer = FFI::MemoryPointer.new :int, 1
|
26
|
+
XDo::FFILib.xdo_mouselocation @_xdo_pointer, x_pointer, y_pointer,
|
27
|
+
screen_pointer
|
28
|
+
[x_pointer.read_int, y_pointer.read_int, screen_pointer.read_int]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Moves the mouse to a new position.
|
32
|
+
def move(x, y, screen)
|
33
|
+
old_location = self.location
|
34
|
+
move_async x, y, screen
|
35
|
+
unless old_location[0, 2] == [x, y]
|
36
|
+
wait_for_move_from old_location[0], old_location[1]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Queues a mouse move request to the X server.
|
41
|
+
def move_async(x, y, screen)
|
42
|
+
XDo::FFILib.xdo_mousemove @_xdo_pointer, x, y, screen
|
43
|
+
end
|
44
|
+
|
45
|
+
# Moves the mouse relatively to its current position.
|
46
|
+
def move_relative(dx, dy)
|
47
|
+
old_location = self.location
|
48
|
+
move_relative_async dx, dy
|
49
|
+
unless dx == 0 && dy == 0
|
50
|
+
wait_for_move_from old_location[0], old_location[1]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Queues a mouse move request to the X server.
|
55
|
+
def move_relative_async(dx, dy)
|
56
|
+
XDo::FFILib.xdo_mousemove_relative @_xdo_pointer, dx, dy
|
57
|
+
end
|
58
|
+
|
59
|
+
# Blocks until the mouse moves away from a position on screen.
|
60
|
+
def wait_for_move_from(x, y)
|
61
|
+
XDo::FFILib.xdo_mouse_wait_for_move_from @_xdo_pointer, x, y
|
62
|
+
end
|
63
|
+
|
64
|
+
# Blocks until the mouse moves to a position on screen.
|
65
|
+
def wait_for_move_to(x, y)
|
66
|
+
XDo::FFILib.xdo_mouse_wait_for_move_to @_xdo_pointer, x, y
|
67
|
+
end
|
68
|
+
|
69
|
+
# Clicks a mouse button.
|
70
|
+
def click(button)
|
71
|
+
XDo::FFILib.xdo_click @_xdo_pointer, 0, button
|
72
|
+
end
|
73
|
+
|
74
|
+
# Presses a mouse button.
|
75
|
+
def press(button)
|
76
|
+
XDo::FFILib.xdo_mousedown @_xdo_pointer, 0, button
|
77
|
+
end
|
78
|
+
|
79
|
+
# Releases a mouse button.
|
80
|
+
def release(button)
|
81
|
+
XDo::FFILib.xdo_mouseup @_xdo_pointer, 0, button
|
82
|
+
end
|
83
|
+
end # class XDo::Mouse
|
84
|
+
|
85
|
+
end # namespace XDo
|
data/lib/x_do/window.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
# :nodoc: namespace
|
2
|
+
class XDo
|
3
|
+
|
4
|
+
# Wraps an xdolib Window pointer.
|
5
|
+
class Window
|
6
|
+
# Brings a window forward and gives it focus.
|
7
|
+
def activate
|
8
|
+
XDo::FFILib.xdo_window_activate @_xdo_pointer, @_window
|
9
|
+
end
|
10
|
+
|
11
|
+
# Gives the input focus to a window
|
12
|
+
def focus
|
13
|
+
XDo::FFILib.xdo_window_focus @_xdo_pointer, @_window
|
14
|
+
end
|
15
|
+
|
16
|
+
# Moves the window at the top of the stack, making it visible.
|
17
|
+
def raise
|
18
|
+
XDo::FFILib.xdo_window_raise @_xdo_pointer, @_window
|
19
|
+
end
|
20
|
+
|
21
|
+
# The PID of the process owning the window.
|
22
|
+
def pid
|
23
|
+
XDo::FFILib.xdo_window_get_pid @_xdo_pointer, @_window
|
24
|
+
end
|
25
|
+
|
26
|
+
# [x, y] array containing the window's coordinates.
|
27
|
+
def location
|
28
|
+
x_pointer = FFI::MemoryPointer.new :int, 1
|
29
|
+
y_pointer = FFI::MemoryPointer.new :int, 1
|
30
|
+
XDo::FFILib.xdo_get_window_location @_xdo_pointer, @_window, x_pointer,
|
31
|
+
y_pointer, nil
|
32
|
+
[x_pointer.read_int, y_pointer.read_int]
|
33
|
+
end
|
34
|
+
|
35
|
+
# [width, height] array containing the window's size.
|
36
|
+
def size
|
37
|
+
width_pointer = FFI::MemoryPointer.new :int, 1
|
38
|
+
height_pointer = FFI::MemoryPointer.new :int, 1
|
39
|
+
XDo::FFILib.xdo_get_window_size @_xdo_pointer, @_window, width_pointer,
|
40
|
+
height_pointer
|
41
|
+
[width_pointer.read_int, height_pointer.read_int]
|
42
|
+
end
|
43
|
+
|
44
|
+
def move(x, y)
|
45
|
+
move_raw x, y
|
46
|
+
glitched_location = self.location
|
47
|
+
x_decoration = glitched_location.first - x
|
48
|
+
y_decoration = glitched_location.last - y
|
49
|
+
move_raw x - x_decoration, y - y_decoration
|
50
|
+
end
|
51
|
+
|
52
|
+
# Moves this window to a new position.
|
53
|
+
#
|
54
|
+
# The position is given directly to X, and does not account for window
|
55
|
+
# decorations.
|
56
|
+
def move_raw(x, y)
|
57
|
+
old_location = self.location
|
58
|
+
return_value = move_raw_async x, y
|
59
|
+
100.times do
|
60
|
+
break unless self.location == old_location
|
61
|
+
sleep 0.01
|
62
|
+
end
|
63
|
+
return_value
|
64
|
+
end
|
65
|
+
|
66
|
+
# Asks X to move this window to a new position.
|
67
|
+
def move_raw_async(x, y)
|
68
|
+
XDo::FFILib.xdo_window_move @_xdo_pointer, @_window, x, y
|
69
|
+
end
|
70
|
+
|
71
|
+
# Resizes this window.
|
72
|
+
#
|
73
|
+
# Args:
|
74
|
+
# width:: the new window's width
|
75
|
+
# height:: the new window's height
|
76
|
+
# use_hints:: if false, width and height are specified in pixels; otherwise,
|
77
|
+
# the unit is relative to window size hints
|
78
|
+
def resize(width, height, use_hints = false)
|
79
|
+
old_size = self.size
|
80
|
+
return_value = resize_async width, height, use_hints
|
81
|
+
100.times do
|
82
|
+
break unless self.size == old_size
|
83
|
+
sleep 0.01
|
84
|
+
end
|
85
|
+
return_value
|
86
|
+
end
|
87
|
+
|
88
|
+
# Asks X to resize this window.
|
89
|
+
def resize_async(width, height, use_hints = false)
|
90
|
+
flags = use_hints ? XDo::FFILib::Consts::SIZE_U : 0
|
91
|
+
XDo::FFILib.xdo_window_setsize @_xdo_pointer, @_window, width, height, flags
|
92
|
+
end
|
93
|
+
|
94
|
+
# Moves the mouse in window coordinates.
|
95
|
+
def move_mouse(window_x, window_y)
|
96
|
+
old_location = @xdo.mouse.location
|
97
|
+
move_mouse_async window_x, window_y
|
98
|
+
@xdo.mouse.wait_for_move_from old_location[0], old_location[1]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Moves the mouse in window coordinates.
|
102
|
+
def move_mouse_async(window_x, window_y)
|
103
|
+
XDo::FFILib.xdo_mousemove_relative_to_window @_xdo_pointer, @_window,
|
104
|
+
window_x, window_y
|
105
|
+
end
|
106
|
+
|
107
|
+
# Clicks a mouse button.
|
108
|
+
def click_mouse(button)
|
109
|
+
XDo::FFILib.xdo_click @_xdo_pointer, @_window, button
|
110
|
+
end
|
111
|
+
|
112
|
+
# Presses a mouse button.
|
113
|
+
def press_mouse(button)
|
114
|
+
XDo::FFILib.xdo_mousedown @_xdo_pointer, @_window, button
|
115
|
+
end
|
116
|
+
|
117
|
+
# Releases a mouse button.
|
118
|
+
def release_mouse(button)
|
119
|
+
XDo::FFILib.xdo_mouseup @_xdo_pointer, @_window, button
|
120
|
+
end
|
121
|
+
|
122
|
+
# Types a string into this window.
|
123
|
+
def type_string(string, delay = 0.12)
|
124
|
+
XDo::FFILib.xdo_type @_xdo_pointer, @_window, string, (delay * 100_000).to_i
|
125
|
+
end
|
126
|
+
|
127
|
+
# Sends a keysequence to this window.
|
128
|
+
#
|
129
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
130
|
+
def type_keysequence(keysequence, delay = 0.12)
|
131
|
+
XDo::FFILib.xdo_keysequence @_xdo_pointer, @_window, keysequence,
|
132
|
+
(delay * 100_000).to_i
|
133
|
+
end
|
134
|
+
|
135
|
+
# Presses a keysequence in this window.
|
136
|
+
#
|
137
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
138
|
+
def press_keysequence(keysequence, delay = 0.12)
|
139
|
+
XDo::FFILib.xdo_keysequence_down @_xdo_pointer, @_window, keysequence,
|
140
|
+
(delay * 100_000).to_i
|
141
|
+
end
|
142
|
+
|
143
|
+
# Releases a keysequence in this window.
|
144
|
+
#
|
145
|
+
# Examples: "alt+Return", "Alt_L+Tab", "l", "semicolon"
|
146
|
+
def release_keysequence(keysequence, delay = 0.12)
|
147
|
+
XDo::FFILib.xdo_keysequence_up @_xdo_pointer, @_window, keysequence,
|
148
|
+
(delay * 100_000).to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
# Creates a wrapper for an X Window handle.
|
152
|
+
#
|
153
|
+
# This constructor is called internally by XDo#find_windows and client code
|
154
|
+
# should not need to call it directly.
|
155
|
+
#
|
156
|
+
# Args:
|
157
|
+
# xdo:: the XDo wrapping the libxdo context used to get this Window
|
158
|
+
# _window:: the X Window handle to be wrapped
|
159
|
+
def initialize(xdo, _window)
|
160
|
+
@xdo = xdo
|
161
|
+
@_xdo_pointer = xdo._pointer
|
162
|
+
@_window = _window
|
163
|
+
end
|
164
|
+
|
165
|
+
# The XDo context that produced the window.
|
166
|
+
attr_accessor :xdo
|
167
|
+
|
168
|
+
# The underlying X Window handle.
|
169
|
+
attr_accessor :_window
|
170
|
+
|
171
|
+
# :nodoc: underlying window handle should impact equality
|
172
|
+
def ==(other)
|
173
|
+
other.kind_of?(XDo::Window) && @_window == other._window
|
174
|
+
end
|
175
|
+
|
176
|
+
# :nodoc: override hash to match ==
|
177
|
+
def hash
|
178
|
+
_window.hash
|
179
|
+
end
|
180
|
+
end # class XDo::Window
|
181
|
+
|
182
|
+
end # namespace XDo
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'x_do'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
2
|
+
|
3
|
+
describe XDo do
|
4
|
+
describe 'with no display specification' do
|
5
|
+
let(:xdo) { XDo.new }
|
6
|
+
|
7
|
+
it 'should use the value of $DISPLAY' do
|
8
|
+
xdo.display_name.should == ENV['DISPLAY']
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'after close' do
|
12
|
+
before { xdo.close }
|
13
|
+
|
14
|
+
it 'should not accept method calls' do
|
15
|
+
lambda {
|
16
|
+
xdo.display_name
|
17
|
+
}.should raise_error(NoMethodError)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should accept #close without crashing' do
|
21
|
+
lambda {
|
22
|
+
xdo.close
|
23
|
+
}.should_not raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'find_windows' do
|
29
|
+
let(:xdo) { XDo.new }
|
30
|
+
|
31
|
+
describe 'with .* name pattern' do
|
32
|
+
let(:windows) { xdo.find_windows :name => '.*' }
|
33
|
+
|
34
|
+
it 'should return at least 1 element' do
|
35
|
+
windows.should_not be_empty
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should return same number of windows as xdotool' do
|
39
|
+
windows.length.should == `xdotool search --all --name ".*"`.split.length
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should have a XDo::Window as the first element' do
|
43
|
+
windows.first.should be_kind_of(XDo::Window)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should include the active window' do
|
47
|
+
windows.should include(xdo.active_window)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should include the "real" focused window' do
|
51
|
+
windows.should include(xdo.real_focused_window)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'with no conditions' do
|
56
|
+
let(:windows) { xdo.find_windows }
|
57
|
+
|
58
|
+
it 'should include the active window' do
|
59
|
+
windows.should include(xdo.active_window)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should include the "real" focused window' do
|
63
|
+
windows.should include(xdo.real_focused_window)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should include the focused window' do
|
67
|
+
windows.should include(xdo.focused_window)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'with the current PID' do
|
72
|
+
let(:windows) { xdo.find_windows :pid => $PID }
|
73
|
+
|
74
|
+
it 'should not return any windows for console process' do
|
75
|
+
windows.should be_empty
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'active_window' do
|
81
|
+
let(:xdo) { XDo.new }
|
82
|
+
let(:window) { xdo.active_window }
|
83
|
+
|
84
|
+
it 'should be an XDo::Window' do
|
85
|
+
window.should be_kind_of(XDo::Window)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'focused_window' do
|
90
|
+
let(:xdo) { XDo.new }
|
91
|
+
let(:window) { xdo.focused_window }
|
92
|
+
|
93
|
+
it 'should be an XDo::Window' do
|
94
|
+
window.should be_kind_of(XDo::Window)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'mouse' do
|
99
|
+
let(:xdo) { XDo.new }
|
100
|
+
let(:mouse) { xdo.mouse }
|
101
|
+
|
102
|
+
it 'should be an XDo::Mouse' do
|
103
|
+
mouse.should be_kind_of(XDo::Mouse)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'with :0 display name' do
|
108
|
+
let(:display) { ':0'}
|
109
|
+
let(:xdo) { XDo.new display }
|
110
|
+
|
111
|
+
it 'should use given display name' do
|
112
|
+
xdo.display_name.should == display
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'lib_version' do
|
117
|
+
let(:version) { XDo.lib_version }
|
118
|
+
|
119
|
+
it 'should be non-nil' do
|
120
|
+
version.should_not be_nil
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should be non-empty' do
|
124
|
+
version.should_not be_empty
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|