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 +4 -4
- data/CLAUDE.md +47 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -0
- data/example/test.rb +24 -23
- data/lib/X11/display.rb +21 -5
- data/lib/X11/form.rb +26 -12
- data/lib/X11/version.rb +1 -1
- data/lib/X11/window.rb +39 -0
- data/lib/X11.rb +2 -1
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b0aef4dac032e7cc033a474d8b3f19920c2dd18e55a98cdf08329c0dcb9f360e
         | 
| 4 | 
            +
              data.tar.gz: 346955046f31e2e53a61183ddcd9d19db11dab82c9de8b9ea04c92b9f4900e93
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 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
    
    
    
        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 | 
            -
             | 
| 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 | 
            -
             | 
| 36 | 
            -
             | 
| 35 | 
            +
             | 
| 36 | 
            +
            def set_window_opacity(window, opacity)
         | 
| 37 | 
            +
              window.change_property(
         | 
| 37 38 | 
             
                :replace,
         | 
| 38 | 
            -
                 | 
| 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( | 
| 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 | 
            -
             | 
| 91 | 
            +
            window.map
         | 
| 91 92 |  | 
| 92 | 
            -
            $gc = gc =  | 
| 93 | 
            -
            $gc2 =  | 
| 94 | 
            -
            $gc3 =  | 
| 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( | 
| 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. | 
| 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 | 
            -
             | 
| 146 | 
            -
                :ZPixmap,  | 
| 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( | 
| 154 | 
            +
            def render_str(window, x,y, str)
         | 
| 154 155 | 
             
              str.each_byte do |ch|
         | 
| 155 | 
            -
                off = render_glyph( | 
| 156 | 
            +
                off = render_glyph(window, x, y, ch.chr)
         | 
| 156 157 | 
             
                x+= off
         | 
| 157 158 | 
             
              end
         | 
| 158 159 | 
             
            end
         | 
| 159 160 |  | 
| 160 | 
            -
            def redraw( | 
| 161 | 
            -
               | 
| 162 | 
            -
               | 
| 163 | 
            -
               | 
| 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 | 
            -
               | 
| 166 | 
            -
                :ZPixmap,  | 
| 166 | 
            +
              window.put_image(
         | 
| 167 | 
            +
                :ZPixmap, $gc2,
         | 
| 167 168 | 
             
                $png.width, $png.height, 80, 120, 0, 24, $data
         | 
| 168 169 | 
             
              )
         | 
| 169 | 
            -
              render_str( | 
| 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( | 
| 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 <  | 
| 7 | 
            -
              class ConnectionError <  | 
| 8 | 
            -
              class AuthorizationError <  | 
| 9 | 
            -
              class ProtocolError <  | 
| 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 | 
| 879 | 
            -
                Lock | 
| 880 | 
            -
                Control =  | 
| 881 | 
            -
                Mod1 | 
| 882 | 
            -
                Mod2 | 
| 883 | 
            -
                Mod3 | 
| 884 | 
            -
                Mod4 | 
| 885 | 
            -
                Mod5 | 
| 886 | 
            -
                Button1 =  | 
| 887 | 
            -
                Button2 =  | 
| 888 | 
            -
                Button3 =  | 
| 889 | 
            -
                Button4 =  | 
| 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
    
    
    
        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  | 
| 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. | 
| 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:  | 
| 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
         |