vigilem-x11 0.0.3
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.
- checksums.yaml +7 -0
- data/lib/vigilem/x11.rb +69 -0
- data/lib/vigilem/x11/constants.rb +5 -0
- data/lib/vigilem/x11/display.rb +53 -0
- data/lib/vigilem/x11/event_queue.rb +152 -0
- data/lib/vigilem/x11/input_system_handler.rb +75 -0
- data/lib/vigilem/x11/system.rb +37 -0
- data/lib/vigilem/x11/terminal_window_utils.rb +33 -0
- data/lib/vigilem/x11/version.rb +5 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/vigilem/x11/display_spec.rb +72 -0
- data/spec/vigilem/x11/event_queue_spec.rb +152 -0
- data/spec/vigilem/x11/input_system_handler_spec.rb +74 -0
- data/spec/vigilem/x11/system_spec.rb +49 -0
- data/spec/vigilem/x11/terminal_window_utils_spec.rb +29 -0
- data/spec/vigilem/x11_spec.rb +44 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 162ca2f1112eea4acea8fefef0cc1e0bb228d114
|
4
|
+
data.tar.gz: f6082f66f84e01897b736694b311a1e9e47b2e81
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 37d103aab9dafff1e6e9340249521504047fc37895ac5393ae5f46cc859a35f5f45a7b9f24fc3396591dcb18e935363945a6897cf155c851732f9e2d82e1e6a5
|
7
|
+
data.tar.gz: 6e1a02234056c12c0ed2e521d903d054360b902c7556a0c2fe65ab4b08594727bf09aa517e199930c82a81e8003d679705791630b651da7a363ba6011064ebca
|
data/lib/vigilem/x11.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'xlib'
|
2
|
+
|
3
|
+
require 'vigilem/x11/display'
|
4
|
+
|
5
|
+
module Vigilem
|
6
|
+
module X11
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# XQueryTree(Display *display, Window w, Window *root_return,
|
11
|
+
# Window *parent_return, Window **children_return,
|
12
|
+
# unsigned int *nchildren_return);
|
13
|
+
# @see man xquerytree
|
14
|
+
# @param [#to_ptr] display
|
15
|
+
# @param [Integer] w
|
16
|
+
# @param [Hash]
|
17
|
+
# @option :root_return [::FFI::Pointer<:ulong>]
|
18
|
+
# @option :parent_return [::FFI::Pointer<:ulong>]
|
19
|
+
# @option :children_return [::FFI::Pointer]
|
20
|
+
# @option :nchildren_return [::FFI::Pointer<:uint> || Integer]
|
21
|
+
# @return [Fixnum] status
|
22
|
+
def query_tree(display, w, opts={})
|
23
|
+
opts[:root_return] ||= ::FFI::MemoryPointer.new(:ulong, 1)
|
24
|
+
opts[:parent_return] ||= ::FFI::MemoryPointer.new(:ulong, 1)
|
25
|
+
opts[:children_return] ||= ::FFI::MemoryPointer.new(:ulong)
|
26
|
+
opts[:nchildren_return] ||= ::FFI::MemoryPointer.new(:uint, 1)
|
27
|
+
|
28
|
+
raise_nil_arg_error('display', display)
|
29
|
+
raise_nil_arg_error('w', w)
|
30
|
+
|
31
|
+
Xlib::XQueryTree(display, w, opts[:root_return], opts[:parent_return],
|
32
|
+
opts[:children_return], opts[:nchildren_return])
|
33
|
+
opts[:nchildren_return] = opts[:nchildren_return].read_uint
|
34
|
+
opts.each do |k,v|
|
35
|
+
opts[k] = v.read_ulong if opts[k].respond_to? :read_ulong
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# @param [#to_ptr] display
|
41
|
+
# @param [Integer || ::FFI::Pointer] focus_return
|
42
|
+
# @param [Integer || ::FFI::Pointer] revert_to_return
|
43
|
+
# @return [Array<Fixnum, Integer, Fixnum>] exit_code, xwindow id, revert_to_return
|
44
|
+
def get_input_focus(display, focus_return, revert_to_return=nil)
|
45
|
+
display = Vigilem::X11::Display.wrap(display)
|
46
|
+
if not focus_return.is_a? ::FFI::MemoryPointer
|
47
|
+
fr = focus_return
|
48
|
+
focus_return = ::FFI::MemoryPointer.new(:int)
|
49
|
+
focus_return.write_int(fr)
|
50
|
+
end
|
51
|
+
if not revert_to_return.is_a? ::FFI::MemoryPointer
|
52
|
+
rtr = revert_to_return
|
53
|
+
revert_to_return = ::FFI::MemoryPointer.new(:int)
|
54
|
+
revert_to_return.write_int(rtr || 0)
|
55
|
+
end
|
56
|
+
raise_nil_arg_error('display', display)
|
57
|
+
raise_nil_arg_error('focus_return', focus_return)
|
58
|
+
[Xlib.XGetInputFocus(display, focus_return, revert_to_return),
|
59
|
+
focus_return.read_int, revert_to_return.read_int]
|
60
|
+
end
|
61
|
+
|
62
|
+
def raise_nil_arg_error(name, val)
|
63
|
+
raise ArgumentError, "#{name} is #{val.inspect}" if val.nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
require 'vigilem/x11/input_system_handler'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'xlib'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module X11
|
5
|
+
#
|
6
|
+
#
|
7
|
+
class Display < Xlib::Display
|
8
|
+
|
9
|
+
@layout = superclass.layout
|
10
|
+
|
11
|
+
#
|
12
|
+
# @param [Display || FFI::Pointer || String]
|
13
|
+
# display_pointer_or_name
|
14
|
+
def initialize(display_pointer_or_name)
|
15
|
+
if display_pointer_or_name.is_a? ::FFI::Pointer
|
16
|
+
super(display_pointer_or_name)
|
17
|
+
else
|
18
|
+
super(Xlib.XOpenDisplay(display_pointer_or_name))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# @return [Fixnum]
|
24
|
+
def fileno
|
25
|
+
@fileno ||= self[:fd]
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# @return [UNIXSocket]
|
30
|
+
def to_io
|
31
|
+
@io ||= UNIXSocket.for_fd(fileno)
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
alias_method :open, :new
|
36
|
+
|
37
|
+
#
|
38
|
+
# @param [Display || FFI::Pointer || String]
|
39
|
+
# display_obj_pointer_or_name
|
40
|
+
# @return [Display]
|
41
|
+
def wrap(display_obj_pointer_or_name)
|
42
|
+
if display_obj_pointer_or_name.is_a? self
|
43
|
+
display_obj_pointer_or_name
|
44
|
+
else
|
45
|
+
Display.open(display_obj_pointer_or_name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'xlib'
|
2
|
+
|
3
|
+
require 'vigilem/support/obj_space'
|
4
|
+
|
5
|
+
require 'vigilem/core/buffer'
|
6
|
+
|
7
|
+
require 'vigilem/core/eventable'
|
8
|
+
|
9
|
+
require 'vigilem/x11/display'
|
10
|
+
|
11
|
+
module Vigilem
|
12
|
+
module X11
|
13
|
+
#
|
14
|
+
#
|
15
|
+
class EventQueue
|
16
|
+
|
17
|
+
include Core::Buffer
|
18
|
+
|
19
|
+
attr_reader :display
|
20
|
+
|
21
|
+
extend Support::ObjSpace
|
22
|
+
|
23
|
+
class << self
|
24
|
+
#
|
25
|
+
# @param [String || Display || ::FFI::Pointer]
|
26
|
+
# display_pointer_or_name
|
27
|
+
def new(display_obj_pointer_or_name)
|
28
|
+
ret = obj_register(super(display_obj_pointer_or_name))
|
29
|
+
same_display_check!
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# finds an existing EventQueue with the given display or
|
35
|
+
# returns a new one based on the items passed in
|
36
|
+
# @param [Display || FFI::Pointer || String]
|
37
|
+
# display_obj_pointer_or_name
|
38
|
+
# @return [EventQueue]
|
39
|
+
def acquire(display_obj_pointer_or_name)
|
40
|
+
dip = Display.wrap(display_obj_pointer_or_name)
|
41
|
+
eventq = all.find {|evq| evq.fileno == dip.fileno }
|
42
|
+
|
43
|
+
eventq || new(dip)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# @return [Array]
|
48
|
+
def same_display_check
|
49
|
+
all.group_by {|ev| ev.display.fileno }.select {|k, v| v.size > 1 }
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# @param [StandardError] err_type, defaults to ArgumentError
|
54
|
+
# @raise "EventQueues should not have the same display `#{array of event queues with same display}'"
|
55
|
+
# @return [NilClass]
|
56
|
+
def same_display_check!(err_type=ArgumentError)
|
57
|
+
unless (dups = same_display_check).empty?
|
58
|
+
raise err_type, "EventQueues should not have the same display `#{dups}'"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# @param [String || Display || ::FFI::Pointer]
|
66
|
+
# display_pointer_or_name
|
67
|
+
def initialize(display_obj_pointer_or_name)
|
68
|
+
@display = Display.wrap(display_obj_pointer_or_name)
|
69
|
+
end
|
70
|
+
|
71
|
+
# the XPending and items pulled from the queue that
|
72
|
+
# haven't propagated
|
73
|
+
# @return [Fixnum]
|
74
|
+
def pending
|
75
|
+
pending! + _internal_buffer.size
|
76
|
+
end
|
77
|
+
|
78
|
+
# only the number of events returned by XPending
|
79
|
+
# @return [Fixnum]
|
80
|
+
def pending!
|
81
|
+
Xlib.XPending(display!)
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# @return [Xlib::XEvent]
|
86
|
+
def next_event
|
87
|
+
x_event = Xlib::XEvent.new
|
88
|
+
Xlib.XNextEvent(display!, x_event)
|
89
|
+
x_event
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# @return [Fixnum]
|
94
|
+
def fileno
|
95
|
+
@fileno ||= display.fileno
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# @raise [ArgumentError]
|
100
|
+
# @return
|
101
|
+
def display!
|
102
|
+
# a way to validate the pointer to prevent segfault?
|
103
|
+
if display.is_a?(::FFI::Pointer) or display.respond_to?(:to_ptr)
|
104
|
+
display
|
105
|
+
else
|
106
|
+
raise ArgumentError, "Display is a `#{display.inspect}'" +
|
107
|
+
"and doesn't respond to :to_ptr"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# @param [Integer || Range] start_idx_range
|
113
|
+
# @param [Integer] len
|
114
|
+
# @return [Array]
|
115
|
+
def slice!(start_idx_range, len=nil)
|
116
|
+
# this isn;t the most efficient way, but is the
|
117
|
+
# most straight forward
|
118
|
+
pending!.times.map do
|
119
|
+
next_event
|
120
|
+
end.compact.slice!(start_idx_range, *len)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# @raise [NotImplemented]
|
125
|
+
def concat(*args)
|
126
|
+
raise NotImplementedError
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# @raise [NotImplemented]
|
131
|
+
def peek
|
132
|
+
raise NotImplementedError
|
133
|
+
# @todo
|
134
|
+
#if _internal_buffer.size > 0
|
135
|
+
# _internal_buffer[0]
|
136
|
+
#else
|
137
|
+
# if pending! > 0
|
138
|
+
# next_event
|
139
|
+
# end
|
140
|
+
#end
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
#
|
145
|
+
# @return [Array]
|
146
|
+
def _internal_buffer
|
147
|
+
@internal_buffer ||= []
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'vigilem/x11'
|
2
|
+
|
3
|
+
require 'vigilem/core/input_system_handler'
|
4
|
+
|
5
|
+
require 'vigilem/x11/constants'
|
6
|
+
|
7
|
+
require 'vigilem/x11/display'
|
8
|
+
|
9
|
+
require 'vigilem/x11/event_queue'
|
10
|
+
|
11
|
+
module Vigilem
|
12
|
+
module X11
|
13
|
+
#
|
14
|
+
#
|
15
|
+
class InputSystemHandler
|
16
|
+
include Core::InputSystemHandler
|
17
|
+
|
18
|
+
attr_reader :window_xid, :demultiplexer
|
19
|
+
|
20
|
+
#
|
21
|
+
# @param [Integer] win_xid
|
22
|
+
# @param [String || Display || ::FFI::Pointer] display_pointer_or_name
|
23
|
+
# @param [Integer] event_mask
|
24
|
+
def initialize(win_xid, display_obj_pointer_or_name, event_mask=nil)
|
25
|
+
|
26
|
+
initialize_input_system_handler
|
27
|
+
|
28
|
+
display = Display.open(display_obj_pointer_or_name)
|
29
|
+
|
30
|
+
@demultiplexer = Core::Demultiplexer.acquire(EventQueue.new(display), [[self.buffer, {:func => :concat}]]) do |dem|
|
31
|
+
dem.input.respond.fileno == display.fileno
|
32
|
+
end
|
33
|
+
|
34
|
+
@window_xid = win_xid
|
35
|
+
|
36
|
+
self.select_input(event_mask) if event_mask
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
include Core::Eventable
|
41
|
+
|
42
|
+
#
|
43
|
+
# @param [Fixnum] num
|
44
|
+
# @return [Array]
|
45
|
+
def read_many_nonblock(num=1)
|
46
|
+
synchronize {
|
47
|
+
demultiplexer.demux(num)
|
48
|
+
buffer.slice!(0, num)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# @todo handle `X Error of failed request: BadWindow (invalid Window parameter)'
|
53
|
+
# @param [Fixnum]
|
54
|
+
# @return [Fixnum]
|
55
|
+
def select_input(event_mask)
|
56
|
+
Xlib.XSelectInput(demultiplexer.input.display, window_xid, event_mask)
|
57
|
+
end
|
58
|
+
|
59
|
+
def_delegators :'demultiplexer.input', :pending, :display
|
60
|
+
|
61
|
+
# @see http://www.unix.com/man-page/All/3x/XGetInputFocus/
|
62
|
+
# @return [Array<Integer, Fixnum>] [xwindow_id, revert_to_return]
|
63
|
+
def get_input_focus
|
64
|
+
X11.get_input_focus(display, window_xid, 0)[1..-1]
|
65
|
+
end
|
66
|
+
|
67
|
+
# @see ::query_tree
|
68
|
+
# @return [Hash]
|
69
|
+
def query_tree(opts={})
|
70
|
+
X11.query_tree(display, window_xid, opts)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Vigilem
|
2
|
+
module X11
|
3
|
+
module System
|
4
|
+
# gets the
|
5
|
+
# @param [Integer] pid
|
6
|
+
# @return [Integer || NilClass]
|
7
|
+
def ppid_of(pid)
|
8
|
+
to_i!(`ps -p #{pid} -o ppid= 2>&1`.strip)
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# @param [Intger] pid
|
13
|
+
# @return [File]
|
14
|
+
def environ_file(pid='self')
|
15
|
+
file_path = "#{File::SEPARATOR}#{File.join('proc', pid.to_s, 'environ')}"
|
16
|
+
if test ?e, file_path
|
17
|
+
@environ = File.open(file_path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# like #to_i but returns nil if not convertable
|
22
|
+
# @todo move to support/core_ext
|
23
|
+
# @param [String] str
|
24
|
+
# @return [Integer || NilClass]
|
25
|
+
def to_i!(str)
|
26
|
+
if str =~ /^\s*(0+|(0*\.0+))\s*$/
|
27
|
+
0
|
28
|
+
else
|
29
|
+
[str.to_i].find {|i| i != 0 }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
extend self
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'vigilem/x11/system'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module X11
|
5
|
+
#
|
6
|
+
#
|
7
|
+
module TerminalWindowUtils
|
8
|
+
|
9
|
+
extend System
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
# gets the id of the window that spawned this
|
14
|
+
# ruby process
|
15
|
+
# @return [Integer]
|
16
|
+
def window_id
|
17
|
+
return (env = to_i!(ENV['WINDOWID'])) if env
|
18
|
+
|
19
|
+
curr_pid = Process.pid
|
20
|
+
until curr_pid.to_i < 2
|
21
|
+
file = environ_file(curr_pid)
|
22
|
+
if file and (xid = to_i!(file.read.scan(/(?<=WINDOWID=)\d+/)[0]))
|
23
|
+
return xid
|
24
|
+
else
|
25
|
+
curr_pid = ppid_of(curr_pid)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/x11/display'
|
4
|
+
|
5
|
+
describe Vigilem::X11::Display do
|
6
|
+
|
7
|
+
after(:each) do
|
8
|
+
[described_class].each do |klass|
|
9
|
+
(klass.instance_variables - [:@layout]).each do |ivar|
|
10
|
+
klass.send(:remove_instance_variable, ivar)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is a subclass of Xlib::Display' do
|
16
|
+
expect(described_class).to be < Xlib::Display
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'has the same structure as Xlib::Display' do
|
20
|
+
expect(described_class.layout).to eql(Xlib::Display.layout)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#initialize' do
|
24
|
+
it 'takes a pointer and creates a display from it' do
|
25
|
+
expect do
|
26
|
+
described_class.new(Xlib.XOpenDisplay(ENV['DISPLAY']))
|
27
|
+
end.not_to raise_error and be_a described_class
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'takes a display name and creates a Display' do
|
31
|
+
expect do
|
32
|
+
described_class.new(ENV['DISPLAY'])
|
33
|
+
end.not_to raise_error and be_a described_class
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'post_init' do
|
38
|
+
subject { described_class.new(ENV['DISPLAY']) }
|
39
|
+
|
40
|
+
describe '#fileno' do
|
41
|
+
it 'returns the fileno of the associated IO' do
|
42
|
+
expect(subject.fileno).to be_an Integer
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#to_io' do
|
47
|
+
it 'returns the display as IO' do
|
48
|
+
expect(subject.to_io).to be_a IO
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '::wrap' do
|
54
|
+
it 'returns a new display object' do
|
55
|
+
expect { described_class.wrap(ENV['DISPLAY']) }.not_to raise_error and be_a Display
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'takes a pointer and creates a display from it' do
|
59
|
+
expect { described_class.wrap(Xlib.XOpenDisplay(ENV['DISPLAY'])) }.not_to raise_error and be_a Display
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'takes a Display object and returns the same Display object' do
|
63
|
+
dpy = described_class.wrap(ENV['DISPLAY'])
|
64
|
+
expect { described_class.wrap(dpy) }.not_to raise_error and eql(dpy)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#describe '::open' do
|
69
|
+
#
|
70
|
+
#end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/x11/event_queue'
|
4
|
+
|
5
|
+
describe Vigilem::X11::EventQueue do
|
6
|
+
|
7
|
+
let(:dpy) { Vigilem::X11::Display.new(ENV['DISPLAY']) }
|
8
|
+
|
9
|
+
after(:each) do
|
10
|
+
[described_class, Vigilem::X11::Display].each do |klass|
|
11
|
+
(klass.instance_variables - [:@layout]).each do |ivar|
|
12
|
+
klass.send(:remove_instance_variable, ivar)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '::same_display_check' do
|
18
|
+
|
19
|
+
it %q<checks the ::all for EventQueue's that have the same fileno> do
|
20
|
+
ary = [double("EventQueue1", :display => dpy), double("EventQueue2", :display => dpy)]
|
21
|
+
described_class.all.concat(ary)
|
22
|
+
expect(described_class.same_display_check).to eql({ dpy.fileno => ary })
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '::same_display_check!' do
|
28
|
+
|
29
|
+
it %q<checks the ::all for EventQueue's that have the same fileno and raises an Error if some exist> do
|
30
|
+
ary = [double("EventQueue1", :display => dpy), double("EventQueue2", :display => dpy)]
|
31
|
+
described_class.all.concat(ary)
|
32
|
+
expect { described_class.same_display_check! }.to raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#initialize' do
|
38
|
+
it 'accepts a display obj' do
|
39
|
+
expect do
|
40
|
+
described_class.new(dpy)
|
41
|
+
end.to_not raise_error and be_a described_class
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'accepts a display pointer' do
|
45
|
+
expect do
|
46
|
+
described_class.new(Xlib.XOpenDisplay(ENV['DISPLAY']))
|
47
|
+
end.to_not raise_error and be_a described_class
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'accepts a display_name' do
|
51
|
+
expect do
|
52
|
+
described_class.new(ENV['DISPLAY'])
|
53
|
+
end.to_not raise_error and be_a described_class
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '::new' do
|
59
|
+
it 'adds the instance to ' do
|
60
|
+
dpy = described_class.new(ENV['DISPLAY'])
|
61
|
+
expect(described_class.all).to include(dpy)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'calls #same_display_check!' do
|
65
|
+
ary = [double("EventQueue1", :display => dpy), double("EventQueue2", :display => dpy)]
|
66
|
+
described_class.all.concat(ary)
|
67
|
+
expect { described_class.new(dpy) }.to raise_error(ArgumentError)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '::acquire' do
|
72
|
+
it 'returns a new instance if none is found' do
|
73
|
+
described_class.all.replace([])
|
74
|
+
dspy = Vigilem::X11::Display.new(ENV['DISPLAY'])
|
75
|
+
expect(described_class.acquire(dspy)).to be_a described_class
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'returns the instance that has the same display#fileno' do
|
79
|
+
evq = described_class.new(dpy)
|
80
|
+
expect(described_class.acquire(dpy)).to eql(evq)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#pending!' do
|
85
|
+
it 'gets the XPending value' do
|
86
|
+
evq = described_class.new(dpy)
|
87
|
+
num = 1
|
88
|
+
allow(Xlib).to receive(:XPending) { num }
|
89
|
+
expect(evq.pending!).to eql(num)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#pending' do
|
94
|
+
it 'gets the XPending value and the size of the array not yet propagated' do
|
95
|
+
evq = described_class.new(dpy)
|
96
|
+
internal_buf = [Xlib::XEvent.new, Xlib::XEvent.new]
|
97
|
+
evq.send(:_internal_buffer).concat(internal_buf)
|
98
|
+
xpend_ret = 1
|
99
|
+
allow(Xlib).to receive(:XPending) { xpend_ret }
|
100
|
+
expect(evq.pending).to eql(xpend_ret + internal_buf.size)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#next_event' do
|
105
|
+
it 'gets the next event from the xwindow event queue' do
|
106
|
+
allow(Xlib).to receive(:XNextEvent)
|
107
|
+
evq = described_class.new(dpy)
|
108
|
+
expect(evq.next_event).to be_a Xlib::XEvent
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#fileno' do
|
113
|
+
it 'gets the fileno of the display' do
|
114
|
+
evq = described_class.new(dpy)
|
115
|
+
expect(evq.fileno).to eql(evq.fileno)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#slice!' do
|
120
|
+
it 'will get the ' do
|
121
|
+
evq = described_class.new(dpy)
|
122
|
+
allow(evq).to receive(:pending!) { 1 }
|
123
|
+
empty_event = Xlib::XEvent.new
|
124
|
+
allow(evq).to receive(:next_event) { empty_event }
|
125
|
+
expect(evq.slice!(0)).to eql(empty_event)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#concat' do
|
130
|
+
it 'will error, not implemented' do
|
131
|
+
evq = described_class.new(dpy)
|
132
|
+
expect { evq.concat }.to raise_error(NotImplementedError)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#peek' do
|
137
|
+
it 'will error, no implemented' do
|
138
|
+
evq = described_class.new(dpy)
|
139
|
+
expect { evq.concat }.to raise_error(NotImplementedError)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'private' do
|
144
|
+
describe '#_internal_buffer' do
|
145
|
+
it 'defaults to an empty array' do
|
146
|
+
evq = described_class.new(dpy)
|
147
|
+
expect(evq.send(:_internal_buffer)).to eql([])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/x11/input_system_handler'
|
4
|
+
|
5
|
+
describe Vigilem::X11::InputSystemHandler do
|
6
|
+
|
7
|
+
subject { described_class.new(0x12123, (ENV['DISPLAY'] || ::FFI::MemoryPointer.new(:long, 296))) }
|
8
|
+
|
9
|
+
after(:each) do
|
10
|
+
[described_class, Vigilem::X11::EventQueue, Vigilem::Core::Demultiplexer, Vigilem::X11::Display].each do |klass|
|
11
|
+
(klass.instance_variables - [:@layout]).each do |ivar|
|
12
|
+
klass.send(:remove_instance_variable, ivar)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#select_input' do
|
18
|
+
it 'calls XSelectInput' do
|
19
|
+
mask = Xlib::KeyPressMask | Xlib::FocusChangeMask
|
20
|
+
allow(Xlib).to receive(:XSelectInput).with(mask)
|
21
|
+
expect(Xlib).to receive(:XSelectInput).with(subject.demultiplexer.input.display, subject.window_xid, mask)
|
22
|
+
subject.select_input(mask)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#initialize' do
|
27
|
+
|
28
|
+
it 'sets up the window if the window_xid was given' do
|
29
|
+
expect(subject.window_xid).to be_an Integer
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'calls XSelectInput if passed in' do
|
33
|
+
mask = Xlib::KeyPressMask | Xlib::FocusChangeMask
|
34
|
+
allow(Xlib).to receive(:XSelectInput).with(mask)
|
35
|
+
expect(Xlib).to receive(:XSelectInput)
|
36
|
+
Vigilem::X11::EventQueue.all.replace([])
|
37
|
+
described_class.new(0x1111, ::FFI::MemoryPointer.new(:long, 296), mask)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#read_many_nonblock' do
|
42
|
+
it 'reads a max number of events from the event_queue' do
|
43
|
+
allow(subject.demultiplexer.input).to receive(:shift) { [1,2,3] }
|
44
|
+
expect(subject.read_many_nonblock(3)).to eql([1,2,3])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'calls #synchronize' do
|
48
|
+
allow(subject.demultiplexer.input).to receive(:shift) { [1,2,3] }
|
49
|
+
expect(subject).to receive(:synchronize)
|
50
|
+
subject.read_many_nonblock(3)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'sets up the other eventable methods' do
|
54
|
+
allow(subject.demultiplexer.input).to receive(:shift) { [1] }
|
55
|
+
expect { subject.read_one_nonblock }.not_to raise_error and eql([1])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#get_input_focus' do
|
60
|
+
it 'calls ::get_input_focus' do
|
61
|
+
allow(Vigilem::X11).to receive(:get_input_focus)
|
62
|
+
expect(Vigilem::X11).to receive(:get_input_focus).with(subject.display, subject.window_xid, 0) { [1,2,3] }
|
63
|
+
subject.get_input_focus
|
64
|
+
end
|
65
|
+
|
66
|
+
if Xlib.available?
|
67
|
+
it 'returns a Fixnum, and Integer' do
|
68
|
+
allow(described_class).to receive(:get_input_focus).and_call_original
|
69
|
+
expect(subject.get_input_focus).to match [a_kind_of(Fixnum), a_kind_of(Integer)]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/x11/system'
|
4
|
+
|
5
|
+
describe Vigilem::X11::System do
|
6
|
+
|
7
|
+
describe '::to_i!' do
|
8
|
+
it 'returns an Integer if convertable' do
|
9
|
+
expect(described_class.to_i!("1234.1234")).to eql(1234)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns an nil if not convertable' do
|
13
|
+
expect(described_class.to_i!("Sjaldan er ein baran stok")).to be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns 0 when the value is zero' do
|
17
|
+
expect(described_class.to_i!("0")).to eql(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns 0 when the value is zero equivilant' do
|
21
|
+
expect(described_class.to_i!(".00")).to eql(0)
|
22
|
+
end
|
23
|
+
|
24
|
+
it %q<doesn't return 0 if it contains zero> do
|
25
|
+
expect(described_class.to_i!('83886092')).to eql(83886092)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '::environ_file' do
|
30
|
+
it 'defaults to the /proc/self/environ' do
|
31
|
+
expect(described_class.environ_file.path).to eql("/proc/self/environ")
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'gets the environ file of the pid passed in' do
|
35
|
+
expect(described_class.environ_file(Process.pid).path).to eql("/proc/#{Process.pid}/environ")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '::ppid_of' do
|
40
|
+
it 'gets the ppid of the passed in pid' do
|
41
|
+
expect(described_class.ppid_of(Process.pid)).to eql(Process.ppid)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns nil if ppid cannot be found' do
|
45
|
+
expect(described_class.ppid_of(`cat /proc/sys/kernel/pid_max`.to_i + 1)).to be_nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
require 'vigilem/x11/terminal_window_utils'
|
6
|
+
|
7
|
+
describe Vigilem::X11::TerminalWindowUtils do
|
8
|
+
|
9
|
+
describe '::window_id' do
|
10
|
+
it 'returns the id of the window if it exists' do
|
11
|
+
expect(described_class.window_id).to be > 0
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'checks the environ_file if the ENV is empty' do
|
15
|
+
|
16
|
+
ENV['WINDOWID'] = ''
|
17
|
+
allow(described_class).to receive(:environ_file) { Tempfile.new('asdf') }
|
18
|
+
expect(described_class).to receive(:environ_file)
|
19
|
+
described_class.window_id
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns traverses the pid tree to find an WINDOWID in the environ_file' do
|
23
|
+
ENV['WINDOWID'] = ''
|
24
|
+
allow(described_class).to receive(:environ_file) { Tempfile.new('asdf') }
|
25
|
+
expect(described_class.window_id).to be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'vigilem/x11'
|
2
|
+
|
3
|
+
describe Vigilem::X11 do
|
4
|
+
if Xlib.available?
|
5
|
+
|
6
|
+
describe '::get_input_focus' do
|
7
|
+
|
8
|
+
let(:display) { Vigilem::X11::Display.new(ENV['DISPLAY'] || ::FFI::MemoryPointer.new(:long, 296)) }
|
9
|
+
|
10
|
+
let(:win_id) { 0x12123 }
|
11
|
+
|
12
|
+
=begin
|
13
|
+
# this should work, but allow strips out the arguments (or something) and
|
14
|
+
# then ArgumentError: "Invalid Memory object" is raised
|
15
|
+
it 'calls XGetInputFocus' do
|
16
|
+
allow(Xlib).to receive(:XGetInputFocus).with(a_kind_of(::FFI::Struct), a_kind_of(Fixnum), a_kind_of(Fixnum))
|
17
|
+
expect(Xlib).to receive(:XGetInputFocus).with(a_kind_of(::FFI::Struct), a_kind_of(Fixnum), a_kind_of(Fixnum))
|
18
|
+
|
19
|
+
subject.get_input_focus
|
20
|
+
end
|
21
|
+
=end
|
22
|
+
it 'accepts [String],[Fixnum],[Fixnum] returns [Fixnum, Integer, Fixnum]' do
|
23
|
+
expect(described_class.get_input_focus(display, win_id)).to match [
|
24
|
+
a_kind_of(Fixnum), a_kind_of(Integer), a_kind_of(Fixnum)
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'updates window ptr' do
|
29
|
+
window = FFI::MemoryPointer.new(:ulong)
|
30
|
+
window.write_ulong(win_id)
|
31
|
+
described_class.get_input_focus(display, window)
|
32
|
+
expect(window.read_int).not_to eql(win_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'updates revert_to_return ptr' do
|
36
|
+
revert_to_return = FFI::MemoryPointer.new(:int)
|
37
|
+
revert_to_return.write_int(0)
|
38
|
+
described_class.get_input_focus(display, win_id)
|
39
|
+
expect(revert_to_return.read_int).to be_a Fixnum
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,192 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vigilem-x11
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jtzero
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: xlib
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: vigilem-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-given
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: turnip
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: X11 bindings for Vigilem, currently used internally only
|
140
|
+
email:
|
141
|
+
- jtzero511@gmail
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- lib/vigilem/x11.rb
|
147
|
+
- lib/vigilem/x11/constants.rb
|
148
|
+
- lib/vigilem/x11/display.rb
|
149
|
+
- lib/vigilem/x11/event_queue.rb
|
150
|
+
- lib/vigilem/x11/input_system_handler.rb
|
151
|
+
- lib/vigilem/x11/system.rb
|
152
|
+
- lib/vigilem/x11/terminal_window_utils.rb
|
153
|
+
- lib/vigilem/x11/version.rb
|
154
|
+
- spec/spec_helper.rb
|
155
|
+
- spec/vigilem/x11/display_spec.rb
|
156
|
+
- spec/vigilem/x11/event_queue_spec.rb
|
157
|
+
- spec/vigilem/x11/input_system_handler_spec.rb
|
158
|
+
- spec/vigilem/x11/system_spec.rb
|
159
|
+
- spec/vigilem/x11/terminal_window_utils_spec.rb
|
160
|
+
- spec/vigilem/x11_spec.rb
|
161
|
+
homepage: http://rubygems.org/gems/vigilem-x11
|
162
|
+
licenses:
|
163
|
+
- MIT
|
164
|
+
metadata: {}
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - '>='
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
requirements: []
|
180
|
+
rubyforge_project:
|
181
|
+
rubygems_version: 2.4.6
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: X11 bindings for Vigilem
|
185
|
+
test_files:
|
186
|
+
- spec/spec_helper.rb
|
187
|
+
- spec/vigilem/x11/display_spec.rb
|
188
|
+
- spec/vigilem/x11/event_queue_spec.rb
|
189
|
+
- spec/vigilem/x11/input_system_handler_spec.rb
|
190
|
+
- spec/vigilem/x11/system_spec.rb
|
191
|
+
- spec/vigilem/x11/terminal_window_utils_spec.rb
|
192
|
+
- spec/vigilem/x11_spec.rb
|