pure-x11 0.0.7 → 0.0.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37b5a813f478de65ecb12e89bafd332ef219baabac729a1baf29cf016d055347
4
- data.tar.gz: 357ef8cd392bad30e9c2d8a7b6771c5c4fd1dd68f3e77da1544cf93f22df14f0
3
+ metadata.gz: b0aef4dac032e7cc033a474d8b3f19920c2dd18e55a98cdf08329c0dcb9f360e
4
+ data.tar.gz: 346955046f31e2e53a61183ddcd9d19db11dab82c9de8b9ea04c92b9f4900e93
5
5
  SHA512:
6
- metadata.gz: 81d50a93f9df23fe424f4dd62fe10fa09f840ab16eccb5de4d83b0d2f681b3cdb8fc9416e2b818f230399276974cac7455f38bfa1fe66c55968f70fc5c1661bb
7
- data.tar.gz: 00bc7b7851c843a92988c23feacba461e6b9e1c2ef1f27b025c363f452f759492a30d4c1ff5d8117ba6bb4940eaebb19234c5fef9012d6cf8339a2ee143bf875
6
+ metadata.gz: 417b477de5a70c6e0e568e218f007544823e1986c7969bd666bf4a8c9382c2af349ac745c693f3b9fe07aeccc9119fadda5daa6b0dfad6bb388218dc6af2ba03
7
+ data.tar.gz: 153aacfb1fa54955eb14d6b186a65868a803f486c88d55b483a55097b81d545fab3888ebaff3332c1fa0d964d71293a49a08654d6fef71ed7501ab6926028185
data/CLAUDE.md ADDED
@@ -0,0 +1,47 @@
1
+ # Ruby X11 Development Guidelines
2
+
3
+ ## Build Commands
4
+ - Install dependencies: `bundle install`
5
+ - Run all tests: `rake test`
6
+ - Run single test: `ruby test/specific_test.rb`
7
+
8
+ ## Code Style
9
+ - Indentation: 2 spaces
10
+ - Naming: snake_case for methods/variables, CamelCase for classes
11
+ - Constants: ALL_CAPS or CamelCase (matching X11 protocol names)
12
+ - Methods: One-line with `=` for simple methods (Ruby 3 syntax)
13
+ - Error handling: Custom X11 error hierarchy (X11::BasicError, etc.)
14
+ - Imports: require_relative for internal files, require for gems
15
+
16
+ ## Organization
17
+ - Core functionality in lib/X11.rb
18
+ - Components in lib/X11/ directory
19
+ - Protocol definitions using DSL in form.rb
20
+ - Test files in test/ directory with _test.rb suffix
21
+
22
+ ## Testing
23
+ - Uses Minitest::Spec syntax: `_(object).must_equal expected`
24
+ - Tests require helper.rb which sets up the environment
25
+ - Mock objects for testing sockets/connections
26
+
27
+ ## Documentation
28
+ - Comments for complex logic
29
+ - Reference X11 protocol documentation when implementing specs
30
+
31
+ ## Adding X11 Protocol Requests
32
+ 1. Define request form in lib/X11/form.rb:
33
+ ```ruby
34
+ class XRenderFreePicture < BaseForm
35
+ field :req_type, Uint8
36
+ field :render_req_type, Uint8, value: 7
37
+ field :request_length, Uint16, value: 2
38
+ field :picture, Uint32
39
+ end
40
+ ```
41
+ 2. Add helper method in lib/X11/display.rb:
42
+ ```ruby
43
+ def render_free_picture(picture)
44
+ write_request(Form::XRenderFreePicture.new(render_opcode, picture))
45
+ end
46
+ ```
47
+ 3. Update X11::VERSION in lib/X11/version.rb after adding new functionality
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pure-x11 (0.0.6)
4
+ pure-x11 (0.0.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -9,6 +9,16 @@ upstread everything.
9
9
  This library is based off of Mathieu Bouchard's work on his RubyX11 project,
10
10
  and Richard Ramsdens excellent start on Ruby-X11.
11
11
 
12
+ Current known use (all mine...):
13
+
14
+ * [RubyWM](https://github.com/vidarh/rubywm) - Pure Ruby window manager
15
+ * [Skrift-X11](https://github.com/vidarh/skrift-x11) - X11 integration for pure Ruby Truetype font rendering
16
+ * Rebar - not yet published wm toolbar
17
+ * RubyTerm (name TBD) - not yet published version of Ruby terminal
18
+
19
+ If you're thinking of using pure-x11, drop me a note and I'll start being more
20
+ cautious about breaking changes ;)
21
+
12
22
  Contributors
13
23
  ------------
14
24
 
data/example/test.rb CHANGED
@@ -14,7 +14,7 @@ dpy = display = X11::Display.new
14
14
  screen = dpy.screens.first
15
15
  root = screen.root
16
16
 
17
- wid = dpy.create_window(
17
+ window = X11::Window.create(dpy,
18
18
  0, 0, # x,y
19
19
  1000, 600, # w,h
20
20
  # FIXME: WTH isn't depth: 32 working here?
@@ -32,17 +32,18 @@ wid = dpy.create_window(
32
32
  #dpy.next_packet
33
33
  #exit(0)
34
34
 
35
- def set_window_opacity(dpy, wid, opacity)
36
- dpy.change_property(
35
+
36
+ def set_window_opacity(window, opacity)
37
+ window.change_property(
37
38
  :replace,
38
- wid, "_NET_WM_WINDOW_OPACITY",
39
+ "_NET_WM_WINDOW_OPACITY",
39
40
  :cardinal, 32,
40
41
  [(0xffffffff * opacity).to_i].pack("V").unpack("C*")
41
42
  )
42
43
  end
43
44
 
44
45
 
45
- set_window_opacity(dpy, wid, 0.8)
46
+ set_window_opacity(window, 0.8)
46
47
 
47
48
  #p dpy.display_info
48
49
 
@@ -87,11 +88,11 @@ def lookup_keysym(dpy, event)
87
88
  end
88
89
 
89
90
  puts "Mapping"
90
- dpy.map_window(wid)
91
+ window.map
91
92
 
92
- $gc = gc = dpy.create_gc(wid, foreground: 0xff0000)
93
- $gc2 = dpy.create_gc(wid,foreground: 0xffffff, background: 0x444444)
94
- $gc3 = dpy.create_gc(wid)
93
+ $gc = gc = window.create_gc(foreground: 0xff0000)
94
+ $gc2 = window.create_gc(foreground: 0xffffff, background: 0x444444)
95
+ $gc3 = window.create_gc
95
96
 
96
97
 
97
98
  puts "Main loop"
@@ -123,7 +124,7 @@ $sft = SFT.new($f)
123
124
  $sft.x_scale = 15
124
125
  $sft.y_scale = 15
125
126
  $glyphcache = {}
126
- def render_glyph(display, wid, x,y, ch)
127
+ def render_glyph(window, x,y, ch)
127
128
  gid = $sft.lookup(ch.ord)
128
129
  mtx = $sft.gmetrics(gid)
129
130
  data = $glyphcache[gid]
@@ -135,45 +136,45 @@ def render_glyph(display, wid, x,y, ch)
135
136
  # p img
136
137
  data = img.pixels.map {|px|
137
138
  "\0\0"+px.chr+"\0" #+ "\0\0\0"
138
- }.join.force_encoding("ASCII-8BIT")
139
+ }.join.b
139
140
  $glyphcache[gid] = data
140
141
  end
141
142
  depth = 24
142
143
  # p data
143
144
  #p img
144
145
  # p ch
145
- display.put_image(
146
- :ZPixmap, wid, $gc2,
146
+ window.put_image(
147
+ :ZPixmap, $gc2,
147
148
  mtx.min_width,mtx.min_height,
148
149
  x, y - mtx.y_offset, 0, depth, data
149
150
  )
150
151
  mtx.advance_width
151
152
  end
152
153
 
153
- def render_str(display, wid, x,y, str)
154
+ def render_str(window, x,y, str)
154
155
  str.each_byte do |ch|
155
- off = render_glyph(display, wid, x, y, ch.chr)
156
+ off = render_glyph(window, x, y, ch.chr)
156
157
  x+= off
157
158
  end
158
159
  end
159
160
 
160
- def redraw(dpy, wid, gc)
161
- dpy.poly_fill_rectangle(wid, gc, [20,20, 60, 80])
162
- dpy.clear_area(false, wid, 30, 30, 5, 5)
163
- dpy.image_text16(wid, $gc2, 30, 70, "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ")
161
+ def redraw(window, gc)
162
+ window.poly_fill_rectangle(gc, [20,20, 60, 80])
163
+ window.clear_area(false, 30, 30, 5, 5)
164
+ window.image_text16($gc2, 30, 70, "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ")
164
165
  #"\u25f0\u25ef Hello World")
165
- dpy.put_image(
166
- :ZPixmap, wid, $gc2,
166
+ window.put_image(
167
+ :ZPixmap, $gc2,
167
168
  $png.width, $png.height, 80, 120, 0, 24, $data
168
169
  )
169
- render_str(dpy, wid, 30,90, 'HelloWorld')
170
+ render_str(window, 30,90, 'HelloWorld')
170
171
  end
171
172
 
172
173
  loop do
173
174
  pkt = display.next_packet
174
175
  if pkt
175
176
  p pkt
176
- redraw(display, wid, gc) if pkt.is_a?(X11::Form::Expose)
177
+ redraw(window, gc) if pkt.is_a?(X11::Form::Expose)
177
178
 
178
179
  if pkt.is_a?(X11::Form::KeyPress)
179
180
  lookup_keysym(dpy,pkt)
data/lib/X11/display.rb CHANGED
@@ -3,10 +3,16 @@ require 'stringio'
3
3
 
4
4
  module X11
5
5
 
6
- class DisplayError < X11Error; end
7
- class ConnectionError < X11Error; end
8
- class AuthorizationError < X11Error; end
9
- class ProtocolError < X11Error; end
6
+ class DisplayError < X11::BasicError; end
7
+ class ConnectionError < X11::BasicError; end
8
+ class AuthorizationError < X11::BasicError; end
9
+ class ProtocolError < X11::BasicError; end
10
+ class Error < X11::BasicError
11
+ def initialize(pkt)
12
+ super("Error: #{pkt.error}, code=#{pkt.code}, seq=#{pkt.sequence_number}, resource=#{pkt.bad_resource_id}, major=#{pkt.major_opcode}, minor=#{pkt.minor_opcode}")
13
+ @error = pkt
14
+ end
15
+ end
10
16
 
11
17
  class Display
12
18
  attr_accessor :socket
@@ -189,7 +195,7 @@ module X11
189
195
  STDERR.puts "write_sync_req: #{ob.inspect}" if @debug
190
196
  pkt = q.shift
191
197
  STDERR.puts "write_sync_rep: #{pkt.inspect}" if @debug
192
- raise(pkt) if pkt.is_a?(X11::Form::Error)
198
+ raise(X11::Error.new(pkt)) if pkt.is_a?(X11::Form::Error)
193
199
  return pkt if !pkt.is_a?(String)
194
200
  reply ? reply.from_packet(StringIO.new(pkt)) : pkt
195
201
  end
@@ -520,6 +526,8 @@ module X11
520
526
  send_event(propagate, destination, mask, event)
521
527
  end
522
528
 
529
+ def query_tree(...) = write_sync(X11::Form::QueryTree.new(...), X11::Form::QueryTreeReply)
530
+
523
531
  def put_image(*args) = write_request(X11::Form::PutImage.new(*args))
524
532
  def clear_area(*args) = write_request(X11::Form::ClearArea.new(*args))
525
533
  def copy_area(*args) = write_request(X11::Form::CopyArea.new(*args))
@@ -533,6 +541,10 @@ module X11
533
541
  def create_pixmap(depth, drawable, w,h)
534
542
  new_id.tap{|pid| write_request(Form::CreatePixmap.new(depth, pid, drawable, w,h)) }
535
543
  end
544
+
545
+ def free_pixmap(pixmap)
546
+ write_request(Form::FreePixmap.new(pixmap))
547
+ end
536
548
 
537
549
  # XRender
538
550
 
@@ -643,6 +655,10 @@ module X11
643
655
  write_request(Form::XRenderCreateSolidFill.new(render_opcode,fill,color))
644
656
  fill
645
657
  end
658
+
659
+ def render_free_picture(picture)
660
+ write_request(Form::XRenderFreePicture.new(render_opcode, picture))
661
+ end
646
662
 
647
663
  private
648
664
 
data/lib/X11/form.rb CHANGED
@@ -694,6 +694,13 @@ module X11
694
694
  field :width, Uint16
695
695
  field :height, Uint16
696
696
  end
697
+
698
+ class FreePixmap < BaseForm
699
+ field :opcode, Uint8, value: 54
700
+ unused 1
701
+ field :request_length, Uint16, value: 2
702
+ field :pixmap, Pixmap
703
+ end
697
704
 
698
705
  class Str < BaseForm
699
706
  field :name, Uint8, :length, value: ->(str) { str.name.length }
@@ -875,18 +882,18 @@ module X11
875
882
  # FIXME: Events have quite a bit of redundancy, but unfortunately
876
883
  # BaseForm can't handle subclassing well.
877
884
 
878
- Shift = 0x001
879
- Lock = 0x002
880
- Control = 0x004
881
- Mod1 = 0x008
882
- Mod2 = 0x010
883
- Mod3 = 0x0020
884
- Mod4 = 0x0040
885
- Mod5 = 0x0080
886
- Button1 = 0x100
887
- Button2 = 0x200
888
- Button3 = 0x400
889
- Button4 = 0x800
885
+ Shift = 0x0001
886
+ Lock = 0x0002
887
+ Control = 0x0004
888
+ Mod1 = 0x0008
889
+ Mod2 = 0x0010
890
+ Mod3 = 0x0020
891
+ Mod4 = 0x0040
892
+ Mod5 = 0x0080
893
+ Button1 = 0x0100
894
+ Button2 = 0x0200
895
+ Button3 = 0x0400
896
+ Button4 = 0x0800
890
897
  Button5 = 0x1000
891
898
 
892
899
  class Event < BaseForm
@@ -1217,5 +1224,12 @@ module X11
1217
1224
  field :fill, Uint32
1218
1225
  field :color, XRenderColor
1219
1226
  end
1227
+
1228
+ class XRenderFreePicture < BaseForm
1229
+ field :req_type, Uint8
1230
+ field :render_req_type, Uint8, value: 7
1231
+ field :request_length, Uint16, value: 2
1232
+ field :picture, Uint32
1233
+ end
1220
1234
  end
1221
1235
  end
data/lib/X11/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module X11
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.11"
3
3
  end
data/lib/X11/window.rb ADDED
@@ -0,0 +1,39 @@
1
+
2
+ module X11
3
+
4
+ # A simple helper class that makes requests where the
5
+ # target object is a specific window a bit more convenient
6
+ class Window
7
+ attr_reader :dpy, :wid
8
+
9
+ def initialize(dpy,wid)
10
+ @dpy, @wid = dpy,wid
11
+ end
12
+
13
+ def self.create(dpy, ...)
14
+ wid = dpy.create_window(...)
15
+ Window.new(dpy,wid)
16
+ end
17
+
18
+ def query_tree = dpy.query_tree(@wid)
19
+ def map = dpy.map_window(@wid)
20
+ def unmap = dpy.unmap_window(@wid)
21
+ def destroy = dpy.destroy_window(@wid)
22
+ def get_geometry = dpy.get_geometry(@wid)
23
+ def configure(...) = dpy.configure_window(@wid, ...)
24
+ def get_property(...) = dpy.get_property(@wid,...)
25
+ def grab_key(arg, ...) = dpy.grab_key(arg, @wid, ...)
26
+ def grab_button(arg,...) = dpy.grab_button(arg, @wid, ...)
27
+ def change_property(mode, ...) = dpy.change_property(mode, @wid, ...)
28
+ def set_input_focus(mode) = dpy.set_input_focus(mode, @wid)
29
+ def select_input(...) = dpy.select_input(@wid,...)
30
+ def get_window_attributes(...) = dpy.get_window_attributes(@wid,...)
31
+ def change_attributes(...) = dpy.change_window_attributes(@wid,...)
32
+
33
+ def image_text16(...) = dpy.image_text16(@wid, ...)
34
+ def clear_area(arg, ...) = dpy.clear_area(arg, @wid, ...)
35
+ def poly_fill_rectangle(...) = dpy.poly_fill_rectangle(@wid, ...)
36
+ def put_image(type, ...) = dpy.put_image(type, @wid, ...)
37
+ def create_gc(...) = dpy.create_gc(@wid, ...)
38
+ end
39
+ end
data/lib/X11.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module X11
2
- class X11Error < StandardError; end
2
+ class BasicError < StandardError; end
3
3
  end
4
4
 
5
5
  require 'socket'
@@ -9,4 +9,5 @@ require_relative './X11/display'
9
9
  require_relative './X11/screen'
10
10
  require_relative './X11/type'
11
11
  require_relative './X11/form'
12
+ require_relative './X11/window'
12
13
  require_relative './X11/keysyms'
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.7
4
+ version: 0.0.11
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: 2024-01-11 00:00:00.000000000 Z
12
+ date: 2025-03-25 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Pure Ruby X11 bindings
15
15
  email:
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - ".gitignore"
22
+ - CLAUDE.md
22
23
  - Gemfile
23
24
  - Gemfile.lock
24
25
  - LICENSE.txt
@@ -38,6 +39,7 @@ files:
38
39
  - lib/X11/screen.rb
39
40
  - lib/X11/type.rb
40
41
  - lib/X11/version.rb
42
+ - lib/X11/window.rb
41
43
  - ruby-x11.gemspec
42
44
  - test/core_test.rb
43
45
  - test/form_test.rb