pure-x11 0.0.11 → 0.0.13
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 +4 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +5 -3
- data/example/query_pointer.rb +40 -0
- data/example/query_pointer_simple.rb +25 -0
- data/example/test.rb +2 -1
- data/example/test_change_property.rb +100 -0
- data/example/test_intern_atom.rb +34 -0
- data/example/xinerama_info.rb +58 -0
- data/lib/X11/auth.rb +1 -1
- data/lib/X11/display.rb +46 -9
- data/lib/X11/form.rb +86 -10
- data/lib/X11/type.rb +1 -1
- data/lib/X11/version.rb +1 -1
- data/test/core_test.rb +1 -1
- data/test/form_test.rb +4 -2
- data/test/helper.rb +4 -3
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a246edf65b1a46b6c5e81c24757ca4f48fd5ca8bf4e8ae07c02226728e5ffd32
|
4
|
+
data.tar.gz: 3f38198bc1e2c7aa77b95ce4069558c616244ce2985589baad32d9af9103d411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e422c72294013117c23c2b85b3f85f7272b0abb0114762f98b94e079cbdaaaaac3d420d0313fb8464ab2698c5e476444cfec01cd45346252ab0701d74c6c310
|
7
|
+
data.tar.gz: 5fc3dfe0aaa23985fa2cb3d2bfa62f94b9d6e902501890f4f8ea43205bbe907cfb0060965846b359ef24de0201776046577d1cb16e097f114db345edef6ec755
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pure-x11 (0.0.
|
4
|
+
pure-x11 (0.0.13)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
9
|
+
minitest (5.25.5)
|
10
|
+
rake (13.2.1)
|
10
11
|
|
11
12
|
PLATFORMS
|
12
13
|
ruby
|
13
14
|
|
14
15
|
DEPENDENCIES
|
16
|
+
minitest (~> 5.0)
|
15
17
|
pure-x11!
|
16
|
-
rake
|
18
|
+
rake (~> 13.2.1)
|
17
19
|
|
18
20
|
BUNDLED WITH
|
19
21
|
2.4.19
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/X11'
|
3
|
+
|
4
|
+
display = X11::Display.new
|
5
|
+
root = display.screens.first.root
|
6
|
+
|
7
|
+
# Create a simple window
|
8
|
+
window = display.create_window(
|
9
|
+
100, 100, 400, 300,
|
10
|
+
depth: 24,
|
11
|
+
values: { X11::Form::CWBackPixel => 0xFFFFFF }
|
12
|
+
)
|
13
|
+
|
14
|
+
# Select input events (pointer motion)
|
15
|
+
display.select_input(window, X11::Form::PointerMotionMask)
|
16
|
+
|
17
|
+
# Map the window (make it visible)
|
18
|
+
display.map_window(window)
|
19
|
+
|
20
|
+
# Wait for window to be visible
|
21
|
+
sleep(0.5)
|
22
|
+
|
23
|
+
puts "Window created. Moving your mouse over the window will display coordinates."
|
24
|
+
puts "Press Ctrl+C to exit."
|
25
|
+
|
26
|
+
# Main event loop
|
27
|
+
display.run do |event|
|
28
|
+
case event
|
29
|
+
when X11::Form::MotionNotify
|
30
|
+
# Query pointer position relative to window
|
31
|
+
pointer = display.query_pointer(window)
|
32
|
+
puts "Pointer position:"
|
33
|
+
puts " Window: (#{pointer.win_x}, #{pointer.win_y})"
|
34
|
+
puts " Root: (#{pointer.root_x}, #{pointer.root_y})"
|
35
|
+
puts " Child: #{pointer.child == 0 ? 'None' : pointer.child}"
|
36
|
+
puts " Mask: #{pointer.mask.to_s(16)}"
|
37
|
+
puts " Same screen: #{pointer.same_screen}"
|
38
|
+
puts "--------------------"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/X11'
|
3
|
+
|
4
|
+
# Create display connection
|
5
|
+
display = X11::Display.new
|
6
|
+
|
7
|
+
# Get root window of first screen
|
8
|
+
root = display.screens.first.root
|
9
|
+
|
10
|
+
puts "Move your mouse around and watch the coordinates update."
|
11
|
+
puts "Press Ctrl+C to exit."
|
12
|
+
|
13
|
+
# Loop and query pointer position every 0.1 seconds
|
14
|
+
loop do
|
15
|
+
pointer = display.query_pointer(root)
|
16
|
+
|
17
|
+
system("clear") # Clear terminal
|
18
|
+
puts "Pointer position relative to root window:"
|
19
|
+
puts " Root coordinates: (#{pointer.root_x}, #{pointer.root_y})"
|
20
|
+
puts " Window under pointer: #{pointer.child == 0 ? 'None' : pointer.child}"
|
21
|
+
puts " Button/modifier mask: #{pointer.mask.to_s(16)}"
|
22
|
+
puts " Same screen: #{pointer.same_screen}"
|
23
|
+
|
24
|
+
sleep(0.1)
|
25
|
+
end
|
data/example/test.rb
CHANGED
@@ -73,7 +73,8 @@ def update_keymap(dpy)
|
|
73
73
|
(c-0x01000100).
|
74
74
|
chr(Encoding::UTF_32) rescue c.to_s(16)
|
75
75
|
else
|
76
|
-
raise "unknown_#{c.to_s(16)}"
|
76
|
+
#raise "unknown_#{c.to_s(16)}"
|
77
|
+
STDERR.puts "UNKNOWN: #{c.to_s(16)}"
|
77
78
|
end
|
78
79
|
end.each_slice(reply.keysyms_per_keycode).to_a
|
79
80
|
#ks = ks.map {|s| s.compact.sort_by{|x| x.to_s}.uniq }.to_a # This is for testing/ease of reading only
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
|
10
|
+
require 'X11'
|
11
|
+
|
12
|
+
# Connect to the X server
|
13
|
+
display = X11::Display.new
|
14
|
+
root = display.default_root
|
15
|
+
puts "Connected to X server, root window: #{root}"
|
16
|
+
|
17
|
+
# Test 8-bit format (bytes)
|
18
|
+
puts "\nTesting format=8:"
|
19
|
+
property_name = "TEST_PROPERTY_8BIT"
|
20
|
+
property_atom = display.atom(property_name)
|
21
|
+
type_atom = display.atom(:cardinal)
|
22
|
+
|
23
|
+
# Create test data and ensure it's padded to a multiple of 4 bytes
|
24
|
+
test_string = "Hello"
|
25
|
+
test_data = test_string.bytes
|
26
|
+
# Calculate padding needed to make length a multiple of 4
|
27
|
+
padding_needed = (4 - (test_data.length % 4)) % 4
|
28
|
+
test_data += [0] * padding_needed if padding_needed > 0
|
29
|
+
puts "Test data with padding: #{test_data.inspect}"
|
30
|
+
|
31
|
+
# Set the property
|
32
|
+
display.change_property(X11::Form::Replace, root, property_atom, type_atom, 8, test_data)
|
33
|
+
puts "Successfully set 8-bit property '#{property_name}' on root window"
|
34
|
+
|
35
|
+
# Read it back
|
36
|
+
result = display.get_property(root, property_name, type_atom, length: test_data.length)
|
37
|
+
puts "Got result: #{result.value.inspect}"
|
38
|
+
# For 8-bit format, the result might include padding zeros, so let's just verify the actual content
|
39
|
+
if result && result.value.is_a?(String) && result.value.start_with?(test_string)
|
40
|
+
puts "✓ Property format=8 verified"
|
41
|
+
else
|
42
|
+
puts "✗ Property format=8 verification failed"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Test 32-bit format (integers) - single value
|
46
|
+
puts "\nTesting format=32 (single value):"
|
47
|
+
property_name = "TEST_PROPERTY_32BIT_1"
|
48
|
+
property_atom = display.atom(property_name)
|
49
|
+
|
50
|
+
# Single 32-bit integer (already a multiple of 4 bytes)
|
51
|
+
test_int = 123456
|
52
|
+
test_data = [test_int].pack("L").bytes
|
53
|
+
puts "Test data (32-bit): #{test_data.inspect}"
|
54
|
+
|
55
|
+
# Set the property
|
56
|
+
display.change_property(X11::Form::Replace, root, property_atom, type_atom, 32, test_data)
|
57
|
+
puts "Successfully set 32-bit property '#{property_name}' on root window"
|
58
|
+
|
59
|
+
# Read it back
|
60
|
+
result = display.get_property(root, property_name, type_atom)
|
61
|
+
puts "Got result: #{result.value.inspect}"
|
62
|
+
if result && result.value == test_int
|
63
|
+
puts "✓ Property format=32 (single value) verified"
|
64
|
+
else
|
65
|
+
puts "✗ Property format=32 (single value) verification failed"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Test 32-bit format (integers) - two values
|
69
|
+
puts "\nTesting format=32 (two values):"
|
70
|
+
property_name = "TEST_PROPERTY_32BIT_2"
|
71
|
+
property_atom = display.atom(property_name)
|
72
|
+
|
73
|
+
# Two 32-bit integers (8 bytes total - already a multiple of 4)
|
74
|
+
test_ints = [123456, 654321]
|
75
|
+
test_data = test_ints.pack("L*").bytes
|
76
|
+
puts "Test data (32-bit, two values): #{test_data.inspect}"
|
77
|
+
|
78
|
+
# Set the property
|
79
|
+
display.change_property(X11::Form::Replace, root, property_atom, type_atom, 32, test_data)
|
80
|
+
puts "Successfully set 32-bit property '#{property_name}' with two values on root window"
|
81
|
+
|
82
|
+
# Read it back - need to explicitly set length to get both values
|
83
|
+
# Try with a larger length to ensure we get all values
|
84
|
+
result = display.get_property(root, property_name, type_atom, length: 8)
|
85
|
+
puts "Got result: #{result.value.inspect}"
|
86
|
+
|
87
|
+
# The result might be a single value or an array, handle both cases
|
88
|
+
if result
|
89
|
+
got_values = result.value.is_a?(Array) ? result.value : [result.value]
|
90
|
+
if got_values[0] == test_ints[0] && (got_values.length < 2 || got_values[1] == test_ints[1])
|
91
|
+
puts "✓ Property format=32 (two values) verified first value: #{got_values[0]}"
|
92
|
+
puts " Note: Only received #{got_values.length} values" if got_values.length < 2
|
93
|
+
else
|
94
|
+
puts "✗ Property format=32 (two values) verification failed"
|
95
|
+
end
|
96
|
+
else
|
97
|
+
puts "✗ Property format=32 (two values) verification failed - no result"
|
98
|
+
end
|
99
|
+
|
100
|
+
puts "\nTest completed"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
|
10
|
+
require 'X11'
|
11
|
+
|
12
|
+
# Connect to the X server
|
13
|
+
display = X11::Display.new
|
14
|
+
puts "Connected to X server"
|
15
|
+
|
16
|
+
# Test interning a new atom
|
17
|
+
atom_name = "TEST_ATOM_#{Time.now.to_i}"
|
18
|
+
puts "Testing interning a new atom: #{atom_name}"
|
19
|
+
|
20
|
+
# This internally uses the InternAtom request
|
21
|
+
atom_id = display.atom(atom_name)
|
22
|
+
puts "Successfully interned atom, got ID: #{atom_id}"
|
23
|
+
|
24
|
+
# Verify it worked by retrieving the atom name
|
25
|
+
retrieved_name = display.get_atom_name(atom_id)
|
26
|
+
puts "Retrieved atom name: #{retrieved_name.inspect}"
|
27
|
+
|
28
|
+
if retrieved_name == atom_name
|
29
|
+
puts "✓ Atom verification successful"
|
30
|
+
else
|
31
|
+
puts "✗ Atom verification failed: got #{retrieved_name.inspect}, expected #{atom_name.inspect}"
|
32
|
+
end
|
33
|
+
|
34
|
+
puts "Test completed successfully!"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/X11'
|
3
|
+
|
4
|
+
display = X11::Display.new
|
5
|
+
|
6
|
+
puts "Querying Xinerama extension..."
|
7
|
+
|
8
|
+
# Check if Xinerama is available
|
9
|
+
begin
|
10
|
+
xinerama_opcode = display.xinerama_opcode
|
11
|
+
if !xinerama_opcode
|
12
|
+
puts "Xinerama extension not available."
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
puts "Xinerama extension found with opcode: #{xinerama_opcode}"
|
16
|
+
rescue => e
|
17
|
+
puts "Error querying Xinerama extension: #{e.message}"
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
# Query version
|
22
|
+
begin
|
23
|
+
version = display.xinerama_query_version
|
24
|
+
puts "Xinerama version: #{version.major_version}.#{version.minor_version}"
|
25
|
+
rescue => e
|
26
|
+
puts "Error querying Xinerama version: #{e.message}"
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
|
30
|
+
# Check if Xinerama is active
|
31
|
+
begin
|
32
|
+
active = display.xinerama_is_active
|
33
|
+
puts "Xinerama active: #{active}"
|
34
|
+
rescue => e
|
35
|
+
puts "Error checking if Xinerama is active: #{e.message}"
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
if active
|
40
|
+
# Query the screen information
|
41
|
+
begin
|
42
|
+
screens_info = display.xinerama_query_screens
|
43
|
+
puts "\nDetected #{screens_info.screens.length} screen(s):"
|
44
|
+
puts "-" * 50
|
45
|
+
|
46
|
+
screens_info.screens.each_with_index do |screen, index|
|
47
|
+
puts "Screen ##{index + 1}:"
|
48
|
+
puts " Position: (#{screen.x_org}, #{screen.y_org})"
|
49
|
+
puts " Size: #{screen.width} x #{screen.height}"
|
50
|
+
puts "-" * 50
|
51
|
+
end
|
52
|
+
rescue => e
|
53
|
+
puts "Error querying Xinerama screens: #{e.message}"
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
else
|
57
|
+
puts "Xinerama is not active. Unable to query screen information."
|
58
|
+
end
|
data/lib/X11/auth.rb
CHANGED
@@ -36,7 +36,7 @@ module X11
|
|
36
36
|
# If no data is found, returns nil
|
37
37
|
def get_by_hostname(host, family, display_id)
|
38
38
|
host = `hostname`.chomp if host == 'localhost' or host == '127.0.0.1' or host.nil?
|
39
|
-
address = TCPSocket.gethostbyname(host) if family == :Internet # this line does nothing for now
|
39
|
+
# address = TCPSocket.gethostbyname(host) if family == :Internet # this line does nothing for now
|
40
40
|
|
41
41
|
auth_data = nil
|
42
42
|
|
data/lib/X11/display.rb
CHANGED
@@ -20,7 +20,7 @@ module X11
|
|
20
20
|
# Open a connection to the specified display (numbered from 0) on the specified host
|
21
21
|
def initialize(target = ENV['DISPLAY'])
|
22
22
|
target =~ /^([\w.-]*):(\d+)(?:.(\d+))?$/
|
23
|
-
host, display_id,
|
23
|
+
host, display_id, _screen_id = $1, $2, $3
|
24
24
|
family = nil
|
25
25
|
|
26
26
|
@debug = ENV["PUREX_DEBUG"].to_s.strip == "true"
|
@@ -371,19 +371,20 @@ module X11
|
|
371
371
|
def get_property(window, property, type, offset: 0, length: 4, delete: false)
|
372
372
|
property = atom(property)
|
373
373
|
type = atom_enum(type)
|
374
|
+
window_id = window.is_a?(X11::Window) ? window.wid : window
|
374
375
|
|
375
376
|
result = write_sync(Form::GetProperty.new(
|
376
|
-
delete,
|
377
|
+
delete, window_id, property, type, offset, length
|
377
378
|
), Form::Property)
|
378
379
|
|
379
380
|
if result && result.format != 0
|
380
381
|
case result.format
|
381
382
|
when 16
|
382
|
-
result.value = result.value.unpack("v")
|
383
|
-
result.value = result.value.first if length ==
|
383
|
+
result.value = result.value.unpack("v*")
|
384
|
+
result.value = result.value.first if result.value.length == 1
|
384
385
|
when 32
|
385
|
-
result.value = result.value.unpack("V")
|
386
|
-
result.value = result.value.first if length ==
|
386
|
+
result.value = result.value.unpack("V*")
|
387
|
+
result.value = result.value.first if result.value.length == 1
|
387
388
|
end
|
388
389
|
elsif result
|
389
390
|
result.value = nil
|
@@ -393,10 +394,11 @@ module X11
|
|
393
394
|
|
394
395
|
def change_property(mode, window, property, type, format, data)
|
395
396
|
property = atom(property.to_sym) if property.is_a?(Symbol) || property.is_a?(String)
|
397
|
+
window_id = window.is_a?(X11::Window) ? window.wid : window
|
396
398
|
|
397
399
|
mode = open_enum(mode, {replace: 0, prepend: 1, append: 2})
|
398
400
|
type = atom_enum(type)
|
399
|
-
write_request(Form::ChangeProperty.new(mode,
|
401
|
+
write_request(Form::ChangeProperty.new(mode, window_id, property, type, format, data))
|
400
402
|
end
|
401
403
|
|
402
404
|
def list_fonts(...) = write_sync(Form::ListFonts.new(...), Form::ListFontsReply)
|
@@ -515,8 +517,8 @@ module X11
|
|
515
517
|
def send_event(...) = write_request(Form::SendEvent.new(...))
|
516
518
|
def client_message(window: default_root, type: :ClientMessage, format: 32, destination: default_root, mask: 0, data: [], propagate: true)
|
517
519
|
f = {8 => "C20", 16 => "S10", 32 => "L5"}[format]
|
518
|
-
p f
|
519
|
-
data = (Array(data).map{|item|atom(item)} +[0]*20).pack(f)
|
520
|
+
# p f
|
521
|
+
data = (Array(data).map{|item|atom(item)} + [0]*20).pack(f)
|
520
522
|
event = Form::ClientMessage.new(
|
521
523
|
format, 0, window, atom(type), data
|
522
524
|
)
|
@@ -659,6 +661,41 @@ module X11
|
|
659
661
|
def render_free_picture(picture)
|
660
662
|
write_request(Form::XRenderFreePicture.new(render_opcode, picture))
|
661
663
|
end
|
664
|
+
|
665
|
+
# Xinerama extension
|
666
|
+
|
667
|
+
def xinerama_opcode
|
668
|
+
return @xinerama_opcode if @xinerama_opcode
|
669
|
+
@xinerama_opcode = major_opcode("XINERAMA")
|
670
|
+
@xinerama_opcode
|
671
|
+
end
|
672
|
+
|
673
|
+
def xinerama_query_version
|
674
|
+
return @xinerama_version if @xinerama_version
|
675
|
+
@xinerama_version = write_sync(
|
676
|
+
X11::Form::XineramaQueryVersion.new(xinerama_opcode),
|
677
|
+
X11::Form::XineramaQueryVersionReply
|
678
|
+
)
|
679
|
+
end
|
680
|
+
|
681
|
+
def xinerama_is_active
|
682
|
+
result = write_sync(
|
683
|
+
X11::Form::XineramaIsActive.new(xinerama_opcode),
|
684
|
+
X11::Form::XineramaIsActiveReply
|
685
|
+
)
|
686
|
+
result.state != 0
|
687
|
+
end
|
688
|
+
|
689
|
+
def xinerama_query_screens
|
690
|
+
write_sync(
|
691
|
+
X11::Form::XineramaQueryScreens.new(xinerama_opcode),
|
692
|
+
X11::Form::XineramaQueryScreensReply
|
693
|
+
)
|
694
|
+
end
|
695
|
+
|
696
|
+
def query_pointer(window)
|
697
|
+
write_sync(Form::QueryPointer.new(window), Form::QueryPointerReply)
|
698
|
+
end
|
662
699
|
|
663
700
|
private
|
664
701
|
|
data/lib/X11/form.rb
CHANGED
@@ -48,7 +48,7 @@ module X11
|
|
48
48
|
# fetch class level instance variable holding defined fields
|
49
49
|
structs = self.class.structs
|
50
50
|
|
51
|
-
|
51
|
+
structs.map do |s|
|
52
52
|
# fetch value of field set in initialization
|
53
53
|
|
54
54
|
value = s.type == :unused ? nil : instance_variable_get("@#{s.name}")
|
@@ -158,7 +158,7 @@ module X11
|
|
158
158
|
class_eval do
|
159
159
|
if value && value.respond_to?(:call)
|
160
160
|
define_method(name.to_sym) { value.call(self) }
|
161
|
-
|
161
|
+
elsif type != :length && type != :format_length
|
162
162
|
attr_accessor name
|
163
163
|
end
|
164
164
|
end
|
@@ -215,6 +215,10 @@ module X11
|
|
215
215
|
## X11 Packet Defintions
|
216
216
|
##
|
217
217
|
|
218
|
+
class Reply < BaseForm
|
219
|
+
field :reply, Uint8
|
220
|
+
end
|
221
|
+
|
218
222
|
class ClientHandshake < BaseForm
|
219
223
|
field :byte_order, Uint8
|
220
224
|
unused 1
|
@@ -400,7 +404,7 @@ module X11
|
|
400
404
|
class CreateWindow < BaseForm
|
401
405
|
field :opcode, Uint8, value: 1
|
402
406
|
field :depth, Uint8
|
403
|
-
field :request_length, Uint16, value: ->(cw) {
|
407
|
+
field :request_length, Uint16, value: ->(cw) { 8 + cw.value_list.length }
|
404
408
|
field :wid, Window
|
405
409
|
field :parent, Window
|
406
410
|
field :x, Int16
|
@@ -458,6 +462,27 @@ module X11
|
|
458
462
|
field :request_length, Uint16, value: 2
|
459
463
|
field :window, Window
|
460
464
|
end
|
465
|
+
|
466
|
+
class QueryPointer < BaseForm
|
467
|
+
field :opcode, Uint8, value: 38
|
468
|
+
unused 1
|
469
|
+
field :request_length, Uint16, value: 2
|
470
|
+
field :window, Window
|
471
|
+
end
|
472
|
+
|
473
|
+
class QueryPointerReply < Reply
|
474
|
+
field :same_screen, Bool
|
475
|
+
field :sequence_number, Uint16
|
476
|
+
field :reply_length, Uint32
|
477
|
+
field :root, Window
|
478
|
+
field :child, Window
|
479
|
+
field :root_x, Int16
|
480
|
+
field :root_y, Int16
|
481
|
+
field :win_x, Int16
|
482
|
+
field :win_y, Int16
|
483
|
+
field :mask, Uint16
|
484
|
+
unused 6
|
485
|
+
end
|
461
486
|
|
462
487
|
class ChangeSaveSet < BaseForm
|
463
488
|
field :opcode, Uint8, value: 6
|
@@ -553,10 +578,6 @@ module X11
|
|
553
578
|
field :name, String8, :string
|
554
579
|
end
|
555
580
|
|
556
|
-
class Reply < BaseForm
|
557
|
-
field :reply, Uint8
|
558
|
-
end
|
559
|
-
|
560
581
|
class InternAtomReply < Reply
|
561
582
|
unused 1
|
562
583
|
field :sequence_number, Uint16
|
@@ -732,7 +753,7 @@ module X11
|
|
732
753
|
field :opcode, Uint8, value: 55
|
733
754
|
unused 1
|
734
755
|
field :request_length, Uint16, value: ->(cw) {
|
735
|
-
|
756
|
+
4 + cw.value_list.length
|
736
757
|
}
|
737
758
|
field :cid, Gcontext
|
738
759
|
field :drawable, Drawable
|
@@ -781,7 +802,7 @@ module X11
|
|
781
802
|
field :opcode, Uint8, value: 70
|
782
803
|
unused 1
|
783
804
|
field :request_length, Uint16, value: ->(ob) {
|
784
|
-
|
805
|
+
3 + 2*(Array(ob.rectangles).length)
|
785
806
|
}
|
786
807
|
field :drawable, Drawable
|
787
808
|
field :gc, Uint32
|
@@ -1119,7 +1140,7 @@ module X11
|
|
1119
1140
|
field :formats, PictFormInfo, :list
|
1120
1141
|
field :screens, PictScreen, :list
|
1121
1142
|
field :subpixels, Uint32, :list
|
1122
|
-
|
1143
|
+
end
|
1123
1144
|
|
1124
1145
|
class XRenderCreatePicture < BaseForm
|
1125
1146
|
field :req_type, Uint8
|
@@ -1231,5 +1252,60 @@ module X11
|
|
1231
1252
|
field :request_length, Uint16, value: 2
|
1232
1253
|
field :picture, Uint32
|
1233
1254
|
end
|
1255
|
+
|
1256
|
+
# Xinerama extension
|
1257
|
+
# From https://gitlab.freedesktop.org/xorg/proto/xineramaproto/-/blob/master/panoramiXproto.h
|
1258
|
+
class XineramaQueryVersion < BaseForm
|
1259
|
+
field :req_type, Uint8
|
1260
|
+
field :xinerama_req_type, Uint8, value: 0
|
1261
|
+
field :request_length, Uint16, value: 2
|
1262
|
+
field :major_version, Uint16, value: 1
|
1263
|
+
field :minor_version, Uint16, value: 0
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
class XineramaQueryVersionReply < Reply
|
1267
|
+
unused 1
|
1268
|
+
field :sequence_number, Uint16
|
1269
|
+
field :reply_length, Uint32
|
1270
|
+
field :major_version, Uint16
|
1271
|
+
field :minor_version, Uint16
|
1272
|
+
unused 20
|
1273
|
+
end
|
1274
|
+
|
1275
|
+
class XineramaIsActive < BaseForm
|
1276
|
+
field :req_type, Uint8
|
1277
|
+
field :xinerama_req_type, Uint8, value: 4
|
1278
|
+
field :request_length, Uint16, value: 1
|
1279
|
+
end
|
1280
|
+
|
1281
|
+
class XineramaIsActiveReply < Reply
|
1282
|
+
unused 1
|
1283
|
+
field :sequence_number, Uint16
|
1284
|
+
field :reply_length, Uint32
|
1285
|
+
field :state, Uint32
|
1286
|
+
unused 20
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
class XineramaScreenInfo < BaseForm
|
1290
|
+
field :x_org, Int16
|
1291
|
+
field :y_org, Int16
|
1292
|
+
field :width, Uint16
|
1293
|
+
field :height, Uint16
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
class XineramaQueryScreens < BaseForm
|
1297
|
+
field :req_type, Uint8
|
1298
|
+
field :xinerama_req_type, Uint8, value: 5
|
1299
|
+
field :request_length, Uint16, value: 1
|
1300
|
+
end
|
1301
|
+
|
1302
|
+
class XineramaQueryScreensReply < Reply
|
1303
|
+
unused 1
|
1304
|
+
field :sequence_number, Uint16
|
1305
|
+
field :reply_length, Uint32
|
1306
|
+
field :screens, Uint32, :length
|
1307
|
+
unused 20
|
1308
|
+
field :screens, XineramaScreenInfo, :list
|
1309
|
+
end
|
1234
1310
|
end
|
1235
1311
|
end
|
data/lib/X11/type.rb
CHANGED
data/lib/X11/version.rb
CHANGED
data/test/core_test.rb
CHANGED
data/test/form_test.rb
CHANGED
@@ -50,12 +50,14 @@ describe X11::Form::BaseForm do
|
|
50
50
|
parent.children << Child.new
|
51
51
|
parent.children << Child.new
|
52
52
|
|
53
|
-
|
53
|
+
_(parent.children.size).must_equal 2
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should encode/decode a packet" do
|
57
57
|
parent = Parent.new(255,Point.new(23,17), "Parent Form", [])
|
58
|
-
|
58
|
+
# Create a mock display object to pass to to_packet
|
59
|
+
mock_display = Object.new
|
60
|
+
socket = MockSocket.new(parent.to_packet(mock_display))
|
59
61
|
|
60
62
|
decoded = Parent.from_packet(socket)
|
61
63
|
_(decoded.value).must_equal 255
|
data/test/helper.rb
CHANGED
@@ -2,10 +2,11 @@ require 'rubygems'
|
|
2
2
|
require 'bundler'
|
3
3
|
Bundler.setup(:default, :development)
|
4
4
|
|
5
|
-
require 'minitest/spec'
|
6
|
-
require 'minitest/autorun'
|
7
|
-
|
8
5
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
6
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
10
7
|
|
8
|
+
# Load minitest before application code to avoid circular require
|
9
|
+
require 'minitest/autorun'
|
10
|
+
|
11
|
+
# Then load application code
|
11
12
|
require 'X11'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pure-x11
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vidar Hokstad
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-
|
12
|
+
date: 2025-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Pure Ruby X11 bindings
|
15
15
|
email:
|
@@ -28,7 +28,12 @@ files:
|
|
28
28
|
- docs/protocol.pdf
|
29
29
|
- example/client_message.rb
|
30
30
|
- example/genie.png
|
31
|
+
- example/query_pointer.rb
|
32
|
+
- example/query_pointer_simple.rb
|
31
33
|
- example/test.rb
|
34
|
+
- example/test_change_property.rb
|
35
|
+
- example/test_intern_atom.rb
|
36
|
+
- example/xinerama_info.rb
|
32
37
|
- lib/X11.rb
|
33
38
|
- lib/X11/auth.rb
|
34
39
|
- lib/X11/display.rb
|