active_window_x 0.0.1

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.
@@ -0,0 +1,47 @@
1
+ # -*- coding:utf-8; mode:ruby; -*-
2
+
3
+ require 'active_window_x'
4
+
5
+ include ActiveWindowX
6
+
7
+ describe RootWindow do
8
+ before do
9
+ @display_raw = mock Xlib::Display
10
+ @display_raw.stub(:kind_of?).with(Data).and_return(true)
11
+ Xlib.stub(:x_open_display).and_return(@display_raw)
12
+ @display = Display.new
13
+ @root_id = 9999
14
+ Xlib.stub(:default_root_window).with(@display_raw).and_return(@root_id)
15
+ @root = @display.root_window
16
+ end
17
+
18
+ describe '#active_window' do
19
+ before do
20
+ @prop_atom = 111
21
+ @active_window_id = 123456
22
+ Xlib.should_receive(:x_intern_atom).with(@display.raw, '_NET_ACTIVE_WINDOW', false).
23
+ and_return(@prop_atom)
24
+ end
25
+ context ', which Xlib::x_get_window_property find an active window,' do
26
+ before do
27
+ Xlib.should_receive(:x_get_window_property).
28
+ with(@display.raw, @root.id, @prop_atom, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
29
+ and_return([0,32,2,0,[@active_window_id,0].pack('l!*')])
30
+ end
31
+ it 'should return the active windows' do
32
+ @display.active_window.id.should == @active_window_id
33
+ end
34
+ end
35
+ context ', which Xlib::x_get_window_property cannot find an active window,' do
36
+ before do
37
+ Xlib.should_receive(:x_get_window_property).
38
+ with(@display.raw, @root.id, @prop_atom, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
39
+ and_return([0,32,2,0,[Xlib::None,0].pack('l!*')])
40
+ end
41
+ it 'should return nil' do
42
+ @display.active_window.should == nil
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,285 @@
1
+ # -*- coding:utf-8; mode:ruby; -*-
2
+
3
+ require 'active_window_x'
4
+
5
+ include ActiveWindowX
6
+
7
+ describe Window do
8
+ before do
9
+ @raw_display = mock Xlib::Display
10
+ @display = mock Display
11
+ @display.stub(:raw){@raw_display}
12
+ @display.stub(:kind_of?).with(Display).and_return(true)
13
+ @id = 123456
14
+ @window = Window.new @display, @id
15
+ end
16
+
17
+ describe '#root' do
18
+ context ', which recive a window from x_query_tree,' do
19
+ before do
20
+ @root = 111
21
+ Xlib.should_receive(:x_query_tree).
22
+ with(@display.raw, @window.id).
23
+ and_return([@root, nil, []])
24
+ end
25
+ it 'should return the root Window' do
26
+ @window.root.id.should == @root
27
+ end
28
+ end
29
+ context ', which recive nil from x_query_tree,' do
30
+ before do
31
+ Xlib.should_receive(:x_query_tree).
32
+ with(@display.raw, @window.id).
33
+ and_return([nil, nil, []])
34
+ end
35
+ it 'should return nil' do
36
+ @window.root.should be_nil
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#parent' do
42
+ context ', which recive a window from x_query_tree,' do
43
+ before do
44
+ @parent = 111
45
+ Xlib.should_receive(:x_query_tree).
46
+ with(@display.raw, @window.id).
47
+ and_return([nil, @parent, []])
48
+ end
49
+ it 'should return the parent Window' do
50
+ @window.parent.id.should == @parent
51
+ end
52
+ end
53
+ context ', which recive nil from x_query_tree,' do
54
+ before do
55
+ Xlib.should_receive(:x_query_tree).
56
+ with(@display.raw, @window.id).
57
+ and_return([nil, nil, []])
58
+ end
59
+ it 'should return nil' do
60
+ @window.root.should be_nil
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#children' do
66
+ before do
67
+ @children = []
68
+ @children.push 111
69
+ @children.push 222
70
+ @children.push 333
71
+ Xlib.should_receive(:x_query_tree).
72
+ with(@display.raw, @window.id).
73
+ and_return([nil, nil, @children])
74
+ end
75
+ it 'should return the child Windows' do
76
+ c = @window.children
77
+ c[0].id.should == @children[0]
78
+ c[1].id.should == @children[1]
79
+ c[2].id.should == @children[2]
80
+ end
81
+ end
82
+
83
+ describe '#title' do
84
+ context ', when the _NET_WM_NAME and WM_NAME prop was not found,' do
85
+ before do
86
+ @window.stub(:prop).with('_NET_WM_NAME').and_return(nil)
87
+ @window.stub(:prop).with('WM_NAME').and_return(nil)
88
+ end
89
+ it 'should return nil' do
90
+ @window.title.should be_nil
91
+ end
92
+ end
93
+ context ', when the WM_NAME prop was found,' do
94
+ before do
95
+ @title = 'foo bar baz'
96
+ @window.stub(:prop).with('_NET_WM_NAME').and_return(nil)
97
+ @window.stub(:prop).with('WM_NAME').and_return(@title)
98
+ end
99
+ it 'should return the value' do
100
+ @window.title.should == @title
101
+ end
102
+ end
103
+ context ', when the _NET_WM_NAME prop was found,' do
104
+ before do
105
+ @title = 'foo bar baz'
106
+ @window.stub(:prop).with('_NET_WM_NAME').and_return(@title)
107
+ end
108
+ it 'should return the value' do
109
+ @window.title.should == @title
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#app_name' do
115
+ context ', when the class prop was not found,' do
116
+ before do
117
+ @window.stub(:prop).with('WM_CLASS').and_return(nil)
118
+ end
119
+ it 'should return nil' do
120
+ @window.app_name.should be_nil
121
+ end
122
+ end
123
+ context ', when the class prop was found,' do
124
+ before do
125
+ @name = "bar"
126
+ @class = "foo"
127
+ @value = "#{@name}\0#{@class}\0"
128
+ @window.stub(:prop).with('WM_CLASS').and_return(@value)
129
+ end
130
+ it 'should return the value' do
131
+ @window.app_name.should == @name
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '#app_class' do
137
+ context ', when the class prop was not found,' do
138
+ before do
139
+ @window.stub(:prop).with('WM_CLASS').and_return(nil)
140
+ end
141
+ it 'should return nil' do
142
+ @window.app_class.should be_nil
143
+ end
144
+ end
145
+ context ', when the class prop was found,' do
146
+ before do
147
+ @name = "bar"
148
+ @class = "foo"
149
+ @value = "#{@name}\0#{@class}\0"
150
+ @window.stub(:prop).with('WM_CLASS').and_return(@value)
151
+ end
152
+ it 'should return the value' do
153
+ @window.app_class.should == @class
154
+ end
155
+ end
156
+ end
157
+
158
+ describe '#pid' do
159
+ context ', when the pid prop was not found,' do
160
+ before do
161
+ @window.stub(:prop).with('_NET_WM_PID').and_return(nil)
162
+ end
163
+ it 'should return nil' do
164
+ @window.pid.should be_nil
165
+ end
166
+ end
167
+ context ', when the pid prop was found,' do
168
+ before do
169
+ @pid = 1111111
170
+ @window.stub(:prop).with('_NET_WM_PID').and_return([@pid])
171
+ end
172
+ it 'should return nil' do
173
+ @window.pid.should == @pid
174
+ end
175
+ end
176
+ end
177
+
178
+ describe '#command' do
179
+ context ', when the pid prop was not found,' do
180
+ before do
181
+ @window.stub(:prop).with('_NET_WM_PID').and_return(nil)
182
+ end
183
+ it 'should return nil' do
184
+ @window.command.should be_nil
185
+ end
186
+ end
187
+ context ', when the pid prop was found,' do
188
+ before do
189
+ @pid = 1111111
190
+ @window.stub(:prop).with('_NET_WM_PID').and_return([@pid])
191
+ @command = 'foobar'
192
+ @path = "/proc/#{@pid}/cmdline"
193
+ File.stub(:readable_real?).with(@path).and_return(true)
194
+ File.stub(:read).with(@path).and_return(@command)
195
+ end
196
+ it 'should return nil' do
197
+ @window.command.should == @command
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#prop' do
203
+ before do
204
+ @prop_id = 1234
205
+ @prop_name = 'FOO'
206
+ @display.should_receive(:intern_atom).with(@prop_name).and_return(@prop_id)
207
+ end
208
+ context 'with a property name, which does not exist for the window,' do
209
+ before do
210
+ Xlib.should_receive(:x_get_window_property).
211
+ with(@display.raw, @window.id, @prop_id, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
212
+ and_return([nil, 0, 0, 0, nil])
213
+ end
214
+ it 'should return nil' do
215
+ @window.prop(@prop_name).should be_nil
216
+ end
217
+ end
218
+ context 'with a property name, which exist for the window and is the long type,' do
219
+ before do
220
+ @prop = [123, 456]
221
+ Xlib.should_receive(:x_get_window_property).
222
+ with(@display.raw, @window.id, @prop_id, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
223
+ and_return([@prop_id, 32, @prop.length, 0, @prop.pack('l!*')])
224
+ end
225
+ it 'should return a Array of Numeric' do
226
+ @window.prop(@prop_name).should == @prop
227
+ end
228
+ end
229
+ context 'with a property name, which exist for the window and is the short type,' do
230
+ before do
231
+ @prop = [12, 34, 46]
232
+ Xlib.should_receive(:x_get_window_property).
233
+ with(@display.raw, @window.id, @prop_id, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
234
+ and_return([@prop_id, 16, @prop.length, 0, @prop.pack('s*')])
235
+ end
236
+ it 'should return a Array of Numeric' do
237
+ @window.prop(@prop_name).should == @prop
238
+ end
239
+ end
240
+ context 'with a property name, which exist for the window and is the char type,' do
241
+ before do
242
+ @prop = "abcdefg\0hijklmn"
243
+ Xlib.should_receive(:x_get_window_property).
244
+ with(@display.raw, @window.id, @prop_id, 0, Window::READ_BUFF_LENGTH, false, Xlib::AnyPropertyType).
245
+ and_return([@prop_id, 8, @prop.length, 0, @prop])
246
+ end
247
+ it 'should return String' do
248
+ @window.prop(@prop_name).should == @prop
249
+ end
250
+ end
251
+ end
252
+
253
+ describe '#prop_atom_ids' do
254
+ context ', which recieve property atoms(Numeric),' do
255
+ before do
256
+ @prop_list = [000, 111, 222]
257
+ Xlib.should_receive(:x_list_properties).and_return(@prop_list)
258
+ end
259
+ it 'shuold return the atoms' do
260
+ @window.prop_atom_ids.should == @prop_list
261
+ end
262
+ end
263
+ context ', which recieve no property atoms,' do
264
+ before do
265
+ @prop_list = nil
266
+ Xlib.should_receive(:x_list_properties){ @prop_list }
267
+ end
268
+ it 'shuold return an empty array' do
269
+ @window.prop_atom_ids.should == []
270
+ end
271
+ end
272
+ end
273
+
274
+ describe '#select_input' do
275
+ context 'with a valid mask' do
276
+ before do
277
+ @mask = Xlib::PropertyChangeMask
278
+ Xlib.should_receive(:x_select_input).with(@display.raw, @id, @mask).and_return(1)
279
+ end
280
+ it 'should call Xlib::x_select_input' do
281
+ @window.select_input @mask
282
+ end
283
+ end
284
+ end
285
+ end
data/spec/xlib_spec.rb ADDED
@@ -0,0 +1,245 @@
1
+ # -*- coding:utf-8; mode:ruby; -*-
2
+
3
+ require 'active_window_x'
4
+ require 'dl'
5
+
6
+ include ActiveWindowX
7
+
8
+ describe Xlib do
9
+ describe '.#x_open_display' do
10
+ context 'with nil' do
11
+ it 'should return a Display' do
12
+ Xlib::x_open_display(nil).class.should == Xlib::Display
13
+ end
14
+ end
15
+ context 'with the default display name' do
16
+ it 'should return a Display' do
17
+ Xlib::x_open_display(ENV['DISPLAY']).class.should == Xlib::Display
18
+ end
19
+ end if ENV['DISPLAY']
20
+ context 'with an invalid display name' do
21
+ it 'should raise a exception' do
22
+ lambda{ Xlib::x_open_display('foo') }.should raise_error(Xlib::UnknownDisplayName)
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '.#x_close_display' do
28
+ context 'with a Display' do
29
+ it 'should return 0' do
30
+ d = Xlib::x_open_display(nil)
31
+ Xlib::x_close_display(d).should == 0
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '.#get_input_focus' do
37
+ before do
38
+ @display = Xlib::x_open_display(nil)
39
+ end
40
+ after do
41
+ Xlib::x_close_display @display
42
+ end
43
+ it 'should return a Array of Number (for window id)' do
44
+ result = Xlib::x_get_input_focus(@display)
45
+ result[0].should be_a Numeric
46
+ result[1].should be_within(0).of(2)
47
+ end
48
+ end
49
+
50
+ describe '.#x_query_tree' do
51
+ before do
52
+ @display = Xlib::x_open_display(nil)
53
+ end
54
+ after do
55
+ Xlib::x_close_display @display
56
+ end
57
+ context 'with the root window' do
58
+ before do
59
+ @root = Xlib::default_root_window(@display)
60
+ end
61
+ it 'should return the root, the parent and then children' do
62
+ result = Xlib::x_query_tree(@display, @root)
63
+ result.shift.should == @root
64
+ result.shift.should be_nil
65
+ children = result.shift
66
+ children.each do |w|
67
+ w.should be_a Numeric
68
+ end
69
+ end
70
+ end
71
+ context 'with a child window of the root window' do
72
+ before do
73
+ @root = Xlib::default_root_window(@display)
74
+ result = Xlib::x_query_tree(@display, @root)
75
+ children = result[2]
76
+ @window = children.first
77
+ end
78
+ it 'should return the root, the parent and then children' do
79
+ result = Xlib::x_query_tree(@display, @window)
80
+ result.shift.should == @root
81
+ result.shift.should be_a Numeric
82
+ children = result.shift
83
+ children.each do |w|
84
+ w.should be_a Numeric
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '.#intern_atom' do
91
+ before do
92
+ @display = Xlib::x_open_display(nil)
93
+ end
94
+ after do
95
+ Xlib::x_close_display @display
96
+ end
97
+ context "with a atom name" do
98
+ it 'should return a Numeric' do
99
+ Xlib::x_intern_atom(@display, "Name", false).should be_a Numeric
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '.#get_atom_name' do
105
+ before do
106
+ @display = Xlib::x_open_display(nil)
107
+ @name = "Name"
108
+ @atom = Xlib::x_intern_atom(@display, @name, false)
109
+ end
110
+ after do
111
+ Xlib::x_close_display @display
112
+ end
113
+ context "with a atom" do
114
+ it 'should return the atom name' do
115
+ Xlib::x_get_atom_name(@display, @atom).should == @name
116
+ end
117
+ end
118
+ end
119
+
120
+ describe '.#get_window_property' do
121
+ before do
122
+ @display = Xlib::x_open_display nil
123
+ @window = Xlib::default_root_window @display
124
+ @length = 1024
125
+ end
126
+ after do
127
+ Xlib::x_close_display @display
128
+ end
129
+ context 'with unknown property' do
130
+ before do
131
+ @name = "FOO"
132
+ @atom = Xlib::x_intern_atom @display, @name, false
133
+ end
134
+ it 'should return a Array such as [Xlib::None, ]' do
135
+ r = Xlib::x_get_window_property(@display, @window, @atom, 0, @length, false, Xlib::AnyPropertyType);
136
+ r.shift.should == Xlib::None
137
+ r.shift.should == 0
138
+ r.shift.should == 0
139
+ r.shift.should == 0
140
+ r.length.should == 1
141
+ end
142
+ end
143
+ context 'with an invalid type and a propery named as "_NET_ACTIVE_WINDOW"' do
144
+ before do
145
+ @name = "_NET_ACTIVE_WINDOW"
146
+ @atom = Xlib::x_intern_atom @display, @name, false
147
+ @window_atom = Xlib::x_intern_atom(@display, "WINDOW", false)
148
+ end
149
+ it 'should return a Array such as [Xlib::None, ]' do
150
+ r = Xlib::x_get_window_property(@display, @window, @atom, 0, @length, false, 10)
151
+ p r
152
+ r.shift.should == @window_atom
153
+ r.shift.should == 32
154
+ r.shift.should == 0
155
+ r.shift.should # == DL::sizeof('l')
156
+ r.length.should == 1
157
+ end
158
+ end
159
+ context 'with an validi type and a propery named as "_NET_ACTIVE_WINDOW"' do
160
+ before do
161
+ @name = "_NET_ACTIVE_WINDOW"
162
+ @atom = Xlib::x_intern_atom @display, @name, false
163
+ @window_atom = Xlib::x_intern_atom(@display, "WINDOW", false)
164
+ end
165
+ it 'should return a Array such as [Xlib::None, ]' do
166
+ r = Xlib::x_get_window_property(@display, @window, @atom, 0, @length, false, @window_atom)
167
+ p r
168
+ r.shift.should == @window_atom
169
+ r.shift.should == 32
170
+ l = r.shift
171
+ r.shift.should
172
+ r.shift.length == DL::sizeof('l') * l
173
+ end
174
+ end
175
+ end
176
+
177
+ describe '.#list_properties' do
178
+ before do
179
+ @display = Xlib::x_open_display nil
180
+ @root = Xlib::default_root_window @display
181
+ end
182
+ after do
183
+ Xlib::x_close_display @display
184
+ end
185
+ context 'with the root window' do
186
+ it 'should return a Array of Numeric' do
187
+ arr = Xlib::x_list_properties(@display, @root)
188
+ arr.should be_a Array
189
+ arr.each{|a| a.should be_a Numeric; }
190
+ end
191
+ end
192
+ context 'with child windows of the root window' do
193
+ before do
194
+ arr = Xlib::x_query_tree @display, @root
195
+ @children = arr[2]
196
+ end
197
+ it 'should return a Array of Numeric' do
198
+ @children.each do |child|
199
+ arr = Xlib::x_list_properties(@display, child)
200
+ if arr
201
+ arr.should be_a Array
202
+ arr.each{|a| a.should be_a Numeric }
203
+ else
204
+ arr.should be_nil
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ describe '.#x_select_input' do
212
+ before do
213
+ @display = Xlib::x_open_display nil
214
+ @root = Xlib::default_root_window @display
215
+ end
216
+ after do
217
+ Xlib::x_close_display @display
218
+ end
219
+ it 'should return a int' do
220
+ ret = Xlib::x_select_input @display, @root, Xlib::PropertyChangeMask
221
+ ret.should be_a Numeric
222
+ end
223
+ end
224
+
225
+ describe '.#x_next_event' do
226
+ before do
227
+ @display = Xlib::x_open_display nil
228
+ @root = Xlib::default_root_window @display
229
+ ret = Xlib::x_select_input @display, @root, Xlib::PropertyChangeMask
230
+ end
231
+ after do
232
+ Xlib::x_close_display @display
233
+ end
234
+ it 'should return an event' do
235
+ puts "\nswitch another window !"
236
+ event = Xlib::x_next_event @display
237
+ event.should be_a Xlib::XPropertyEvent
238
+ event.type.should == Xlib::PropertyNotify
239
+ puts "type:#{event.type}, serial:#{event.serial}, send_event:#{event.send_event},"+
240
+ " display:#{event.display}, window:#{event.window}, atom:#{event.atom},"+
241
+ " time:#{event.time}, state:#{event.state}"
242
+ end if false
243
+ end
244
+
245
+ end if ENV.has_key? 'DISPLAY' # if X Window System running, this spec should be executed
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_window_x
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Keiichiro Ui
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: bundler
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ description: ActiveWindowX is a gem to observe an active window on Linux (X Window System).
63
+ email:
64
+ - keiichiro.ui@gmail.com
65
+ executables: []
66
+
67
+ extensions:
68
+ - ext/active_window_x/extconf.rb
69
+ extra_rdoc_files: []
70
+
71
+ files:
72
+ - .gitignore
73
+ - Gemfile
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - active_window_x.gemspec
78
+ - ext/active_window_x/extconf.rb
79
+ - ext/active_window_x/xlib.c
80
+ - lib/active_window_x.rb
81
+ - lib/active_window_x/atom.rb
82
+ - lib/active_window_x/client_message_event.rb
83
+ - lib/active_window_x/display.rb
84
+ - lib/active_window_x/event.rb
85
+ - lib/active_window_x/event_listener.rb
86
+ - lib/active_window_x/property_event.rb
87
+ - lib/active_window_x/root_window.rb
88
+ - lib/active_window_x/version.rb
89
+ - lib/active_window_x/window.rb
90
+ - lib/active_window_x/xid.rb
91
+ - sample/active_window_dump.rb
92
+ - sample/simple.rb
93
+ - spec/atom_spec.rb
94
+ - spec/display_spec.rb
95
+ - spec/root_window_spec.rb
96
+ - spec/window_spec.rb
97
+ - spec/xlib_spec.rb
98
+ homepage: https://github.com/kui/active_window_x
99
+ licenses: []
100
+
101
+ post_install_message:
102
+ rdoc_options: []
103
+
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.7.2
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: observer an active window on Linux (X Window System).
131
+ test_files:
132
+ - spec/atom_spec.rb
133
+ - spec/display_spec.rb
134
+ - spec/root_window_spec.rb
135
+ - spec/window_spec.rb
136
+ - spec/xlib_spec.rb