pure-x11 0.0.2 → 0.0.4

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: c3d89e6c8da43a6f489333c1d50f85485f1357bc0549747f11dbc2cf325e3af1
4
- data.tar.gz: 9b7ddd2b688c8c5d924a027a1d05b65744b52ad7f84a7e646c26ec610fb93d8e
3
+ metadata.gz: 51d974fee51d60b334a5e5f26bb5e0d90f8628e09930da7bb6c97145b3718ed9
4
+ data.tar.gz: 2312f1c9f7e0d2b5391bb15aab15805e802635d53d6fe1d90cf22f0c2112b117
5
5
  SHA512:
6
- metadata.gz: ab203eb42daeda7e2091becae8de88582291ae8a7636035ed017f86e6195f928d2e7ff5945c356363ddba5ed63f7623158ac0004156cf76d5ff7e75092c32583
7
- data.tar.gz: 361fb690e60345acf764192386fc511a3ade0c724bb48f7f585fc573dcfe6c50386e7098e875d697a2be9406578c1c75ab7c57ddacda78dd8cc303067ee72bbc
6
+ metadata.gz: 226fbfc35ff75f2fa95fabf09a7d0e4c72cd99f1678cd607e8421ed26750118e40291686a582c01b0ae296dfcefc5e7038bd3d3025f9b678e5a1fa35c2465135
7
+ data.tar.gz: 69363b78df087ea43799f06c8477d008d15b721bcd604a52e1eb3b33411a102fcf4d33f3262ac0c0de5fa76de9262d489eaaca85e043f5251bb41563959970fd
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pure-x11 (0.0.2)
4
+ pure-x11 (0.0.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,8 +1,13 @@
1
- Ruby X11
1
+ Pure X11
2
2
  ========
3
3
 
4
+ This library is now on Rubygems.org as "pure-X11" as I (vidarh) has not had a
5
+ response from the original author. If that should change, I'll be happy to
6
+ upstread everything.
7
+
4
8
  (under-development) Pure Ruby implementation of the X Window System Protocol.
5
- This library is based off of Mathieu Bouchard's work on his RubyX11 project.
9
+ This library is based off of Mathieu Bouchard's work on his RubyX11 project,
10
+ and Richard Ramsdens excellent start on Ruby-X11.
6
11
 
7
12
  Contributors
8
13
  ------------
data/example/test.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'skrift'
2
3
  require 'bundler'
3
4
  require 'chunky_png'
4
5
  Bundler.setup(:default, :development)
@@ -8,95 +9,164 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
9
 
9
10
  require 'X11'
10
11
 
11
- display = X11::Display.new
12
- screen = display.screens.first
12
+
13
+ dpy = display = X11::Display.new
14
+ screen = dpy.screens.first
13
15
  root = screen.root
14
16
  wid = display.new_id
15
- display.write_request(X11::Form::CreateWindow.new(
16
- screen.root_depth,
17
- wid,
18
- root,
19
- 0, #x
20
- 0, #y
21
- 1000,#w
22
- 600,#h
17
+
18
+ dpy.create_window(
19
+ screen.root_depth, wid, root,
20
+ 0, 0, # x,y
21
+ 1000, 600, # w,h
23
22
  0,
24
23
  X11::Form::InputOutput,
25
24
  X11::Form::CopyFromParent,
26
25
  X11::Form::CWBackPixel |
27
26
  X11::Form::CWEventMask,
28
- [0xff8844, # RGB background
27
+ [0x0, # RGB background
29
28
  X11::Form::SubstructureNotifyMask |
30
- # X11::Form::StructureNotifyMask | ## Move
29
+ X11::Form::StructureNotifyMask | ## Move
31
30
  X11::Form::ExposureMask |
32
31
  X11::Form::KeyPressMask |
33
32
  X11::Form::ButtonPressMask
34
33
  ]
35
- ))
34
+ )
35
+
36
+ def set_window_opacity(dpy, wid, opacity)
37
+ dpy.change_property(
38
+ X11::Form::Replace,
39
+ wid, dpy.atom(:_NET_WM_WINDOW_OPACITY),
40
+ X11::Form::CardinalAtom, 32,
41
+ [(0xffffffff * opacity).to_i].pack("N").split(//).map(&:ord)
42
+ )
43
+ end
44
+
45
+
46
+ set_window_opacity(dpy, wid, 0.8)
47
+ #p dpy.display_info
48
+
49
+ #reply = dpy.query_extension("XKEYBOARD")
50
+
51
+ $kmap = nil
52
+ def update_keymap(dpy)
53
+ reply = dpy.get_keyboard_mapping
54
+
55
+
56
+ if reply
57
+ $kmap = reply.keysyms.map do |c|
58
+ if c == 0
59
+ nil
60
+ elsif X11::KeySyms[c]
61
+ X11::KeySyms[c]
62
+ elsif c < 0x100
63
+ c.chr(Encoding::ISO_8859_1)
64
+ elsif c.between?(0xffb0, 0xffb9)
65
+ "KP_#{c-0xffb0}".to_sym
66
+ elsif c.between?(0xffbe, 0xffe0)
67
+ "F#{c-0xffbe+1}".to_sym
68
+ elsif c.between?(0xff08, 0xffff)
69
+ # FIIXME:
70
+ raise "keyboard_#{c.to_s(16)}".to_s
71
+ elsif c.between?(0x01000100, 0x0110FFFF)
72
+ (c-0x01000100).
73
+ chr(Encoding::UTF_32) rescue c.to_s(16)
74
+ else
75
+ raise "unknown_#{c.to_s(16)}"
76
+ end
77
+ end.each_slice(reply.keysyms_per_keycode).to_a
78
+ #ks = ks.map {|s| s.compact.sort_by{|x| x.to_s}.uniq }.to_a # This is for testing/ease of reading only
79
+ p $kmap[47-dpy.display_info.min_keycode]
80
+ end
81
+ end
82
+
83
+
84
+ def lookup_keysym(dpy, event)
85
+ update_keymap(dpy) if !$kmap
86
+ p $kmap[event.detail-dpy.display_info.min_keycode]
87
+ end
88
+
36
89
  puts "Mapping"
37
- display.write_request(X11::Form::MapWindow.new(wid))
38
- # Creating GC
39
- gc = display.new_id
40
- display.write_request(X11::Form::CreateGC.new(
41
- gc, screen.root,
42
- X11::Form::ForegroundMask,
43
- [0xff0000, # RGB foreground
44
- ]
45
- ))
46
-
47
- $gc2 = display.new_id
48
- display.write_request(X11::Form::CreateGC.new(
49
- $gc2,
50
- screen.root,
51
- X11::Form::ForegroundMask|X11::Form::BackgroundMask,
52
- [0xffffff, # RGB foreground
53
- 0x444444,
54
- ]
55
- ))
90
+ dpy.map_window(wid)
56
91
 
57
- $gc3 = display.new_id
58
- display.write_request(X11::Form::CreateGC.new(
59
- $gc3,
60
- screen.root,
61
- 0, []
62
- ))
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)
63
95
 
64
96
 
65
97
  puts "Main loop"
66
- p gc
67
98
 
68
- # This will wait for a reply
69
- p display.write_sync(X11::Form::ListFonts.new(10, "*7x13*"),
70
- X11::Form::ListFontsReply).names.map(&:to_s)
99
+ #p dpy.list_fonts(10, "*7x13*").names.map(&:to_s)
71
100
 
72
- fid = display.new_id
73
- display.write_request(X11::Form::OpenFont.new(fid, "7x13"))
74
- display.write_request(X11::Form::ChangeGC.new($gc2, X11::Form::FontMask, [fid]))
101
+ fid = dpy.new_id
102
+ dpy.open_font(fid, "-misc-fixed-bold-r-normal--13-120-75-75-c-70-iso10646-1")
103
+ #"-bitstream-courier 10 pitch-medium-r-normal--0-0-0-0-m-0-iso10646-1")
104
+ dpy.change_gc($gc2, X11::Form::FontMask, [fid])
75
105
 
76
106
  $png = ChunkyPNG::Image.from_file('genie.png')
77
- p $png.width
78
- p $png.height
79
107
 
80
- def redraw(display, wid, gc)
81
- p [:redraw, gc]
82
- display.write_request(X11::Form::PolyFillRectangle.new(
83
- wid, gc,
84
- [X11::Form::Rectangle.new(20,20, 60, 80)]
85
- ))
108
+ $data = ""
109
+ $png.pixels.each do |px|
110
+ str = [px].pack("N")
111
+ if str[3] == "\x00"
112
+ $data << "\0\0\0\0".force_encoding("ASCII-8BIT")
113
+ else
114
+ $data << str[2] << str[1] << str[0] << str[3]
115
+ end
116
+ end
86
117
 
87
- display.write_request(X11::Form::ClearArea.new( false, wid, 30, 30, 5, 5))
88
- display.write_request(X11::Form::ImageText8.new(wid, $gc2, 30, 70, "Hello World"))
118
+ #$f = Font.load("/usr/share/fonts/truetype/tlwg/Umpush-BoldOblique.ttf")
119
+ $f = Font.load("/usr/share/fonts/truetype/tlwg/Garuda.ttf")
120
+ #$f = Font.load("resources/FiraGO-Regular.ttf")
89
121
 
122
+ $sft = SFT.new($f)
123
+ $sft.x_scale = 15
124
+ $sft.y_scale = 15
125
+ $glyphcache = {}
126
+ def render_glyph(display, wid, x,y, ch)
127
+ gid = $sft.lookup(ch.ord)
128
+ mtx = $sft.gmetrics(gid)
129
+ data = $glyphcache[gid]
130
+ if !data
131
+ img = Image.new(mtx.min_width, mtx.min_height) #(mtx .min_width + 3) & ~3, mtx.min_height)
132
+ if !$sft.render(gid, img)
133
+ raise "Unable to render #{gid}\n"
134
+ end
135
+ # p img
136
+ data = img.pixels.map {|px|
137
+ "\0\0"+px.chr+"\0" #+ "\0\0\0"
138
+ }.join.force_encoding("ASCII-8BIT")
139
+ $glyphcache[gid] = data
140
+ end
90
141
  depth = 24
91
- # FIXME: The colors are wrong
92
- # pixels.pack("N*")
93
- data = ""
94
- $png.pixels.each do |px|
95
- str = [px].pack("N")
96
- data << str[2] << str[1] << str[0] << str[3]
142
+ # p data
143
+ #p img
144
+ # p ch
145
+ display.put_image(
146
+ X11::Form::ZPixmap, wid, $gc2,
147
+ mtx.min_width,mtx.min_height,
148
+ x, y - mtx.y_offset, 0, depth, data
149
+ )
150
+ mtx.advance_width
151
+ end
152
+
153
+ def render_str(display, wid, x,y, str)
154
+ str.each_byte do |ch|
155
+ off = render_glyph(display, wid, x, y, ch.chr)
156
+ x+= off
97
157
  end
98
- display.write_request(X11::Form::PutImage.new(
99
- X11::Form::ZPixmap, wid, $gc2, $png.width, $png.height, 80, 80, 0, depth, data))
158
+ end
159
+
160
+ def redraw(dpy, wid, gc)
161
+ dpy.poly_fill_rectangle(wid, gc, [X11::Form::Rectangle.new(20,20, 60, 80)])
162
+ dpy.clear_area(false, wid, 30, 30, 5, 5)
163
+ dpy.image_text16(wid, $gc2, 30, 70, "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ")
164
+ #"\u25f0\u25ef Hello World")
165
+ dpy.put_image(
166
+ X11::Form::ZPixmap, wid, $gc2,
167
+ $png.width, $png.height, 80, 120, 0, 24, $data
168
+ )
169
+ render_str(dpy, wid, 30,90, 'HelloWorld')
100
170
  end
101
171
 
102
172
  loop do
@@ -104,5 +174,9 @@ loop do
104
174
  if pkt
105
175
  p pkt
106
176
  redraw(display, wid, gc) if pkt.is_a?(X11::Form::Expose)
177
+
178
+ if pkt.is_a?(X11::Form::KeyPress)
179
+ lookup_keysym(dpy,pkt)
180
+ end
107
181
  end
108
182
  end
data/lib/X11/display.rb CHANGED
@@ -26,7 +26,8 @@ module X11
26
26
  family = :Internet
27
27
  end
28
28
 
29
- authorize(host, family, display_id)
29
+ # FIXME
30
+ authorize(host, family, display_id) rescue nil
30
31
 
31
32
  @requestseq = 1
32
33
  @queue = []
@@ -86,6 +87,8 @@ module X11
86
87
  return Form::KeyRelease.from_packet(StringIO.new(data))
87
88
  when 4
88
89
  return Form::ButtonPress.from_packet(StringIO.new(data))
90
+ when 5
91
+ return Form::ButtonRelease.from_packet(StringIO.new(data))
89
92
  when 6
90
93
  return Form::MotionNotify.from_packet(StringIO.new(data))
91
94
  when 12
@@ -177,9 +180,46 @@ module X11
177
180
  end
178
181
  end
179
182
 
183
+ def find_visual(screen, depth, qlass = 4)
184
+ self.display_info.screens[screen].depths.find{|d|
185
+ d.depth == depth }.visuals.find{|v| v.qlass = qlass }
186
+ end
187
+
180
188
  # Requests
181
- def create_window(*args)
182
- write_request(X11::Form::CreateWindow.new(*args))
189
+ def create_window(x,y,w,h,
190
+ values: {},
191
+ depth: 32, parent: nil, border_width: 0, wclass: X11::Form::InputOutput, visual: nil
192
+ )
193
+ wid = new_id
194
+ parent ||= screens.first.root
195
+
196
+
197
+ if visual.nil?
198
+ visual = find_visual(0, depth).visual_id
199
+ end
200
+
201
+
202
+ values[X11::Form::CWColorMap] ||= create_colormap(0, parent, visual)
203
+
204
+ values = values.sort_by{_1[0]}
205
+ mask = values.inject(0) {|acc,v| (acc | v[0]) }
206
+ values = values.map{_1[1]}
207
+ write_request(
208
+ X11::Form::CreateWindow.new(
209
+ depth, wid, parent,
210
+ x,y,w,h,border_width, wclass, visual, mask, values)
211
+ )
212
+ return wid
213
+ end
214
+
215
+ def change_window_attributes(wid,
216
+ values: {})
217
+ values = values.sort_by{_1[0]}
218
+ mask = values.inject(0) {|acc,v| (acc | v[0]) }
219
+ values = values.map{_1[1]}
220
+ write_request(
221
+ X11::Form::ChangeWindowAttributes.new(wid, mask, values)
222
+ )
183
223
  end
184
224
 
185
225
  def atom(name)
@@ -211,6 +251,14 @@ module X11
211
251
  end
212
252
  end
213
253
 
254
+ def destroy_window(window)
255
+ write_request(X11::Form::DestroyWindow.new(window))
256
+ end
257
+
258
+ def get_geometry(drawable)
259
+ write_sync(X11::Form::GetGeometry.new(drawable), X11::Form::Geometry)
260
+ end
261
+
214
262
  def get_keyboard_mapping(min_keycode=display_info.min_keycode, count= display_info.max_keycode - min_keycode)
215
263
  write_sync(X11::Form::GetKeyboardMapping.new(min_keycode, count), X11::Form::GetKeyboardMappingReply)
216
264
  end
@@ -242,6 +290,77 @@ module X11
242
290
  write_request(X11::Form::MapWindow.new(*args))
243
291
  end
244
292
 
293
+ def grab_key(owner_events, grab_window, modifiers, keycode, pointer_mode, keyboard_mode)
294
+ write_request(X11::Form::GrabKey.new(
295
+ owner_events,
296
+ grab_window,
297
+ modifiers,
298
+ keycode,
299
+ pointer_mode == :async ? 1 : 0,
300
+ keyboard_mode == :async ? 1 : 0
301
+ ))
302
+ end
303
+
304
+ def grab_button(owner_events, grab_window, event_mask, pointer_mode,
305
+ keyboard_mode, confine_to, cursor, button, modifiers)
306
+ write_request(X11::Form::GrabButton.new(
307
+ owner_events, grab_window, event_mask,
308
+ pointer_mode == :async ? 1 : 0,
309
+ keyboard_mode == :async ? 1 : 0,
310
+ confine_to.to_i, cursor.to_i, button, modifiers)
311
+ )
312
+ end
313
+
314
+ def configure_window(window, x: nil, y: nil, width: nil, height: nil,
315
+ border_width: nil, sibling: nil, stack_mode: nil)
316
+
317
+ mask = 0
318
+ values = []
319
+
320
+ if x
321
+ mask |= 0x001
322
+ values << x
323
+ end
324
+
325
+ if y
326
+ mask |= 0x002
327
+ values << y
328
+ end
329
+
330
+ if width
331
+ mask |= 0x004
332
+ values << width
333
+ end
334
+
335
+ if height
336
+ mask |= 0x008
337
+ values << height
338
+ end
339
+
340
+ if border_width
341
+ mask |= 0x010
342
+ values << border_width
343
+ end
344
+
345
+ if sibling
346
+ mask |= 0x020
347
+ values << sibling
348
+ end
349
+
350
+ if stack_mode
351
+ mask |= 0x040
352
+ values << case stack_mode
353
+ when :above then 0
354
+ when :below then 1
355
+ when :top_if then 2
356
+ when :bottom_if then 3
357
+ when :opposite then 4
358
+ else raise "Unknown stack_mode #{stack_mode.inspect}"
359
+ end
360
+ end
361
+ write_request(X11::Form::ConfigureWindow.new(window, mask, values))
362
+ end
363
+
245
364
 
246
365
  def create_gc(window, foreground: nil, background: nil)
247
366
  mask = 0
@@ -329,7 +448,7 @@ module X11
329
448
  s.depths.map do |d|
330
449
  d.visuals.map {|v| v.visual == visual ? v : nil }
331
450
  end
332
- end.flatten.compact.first.format
451
+ end.flatten.compact.first&.format
333
452
  end
334
453
 
335
454
  def render_find_standard_format(sym)
@@ -411,7 +530,12 @@ module X11
411
530
  auth = Auth.new
412
531
  auth_info = auth.get_by_hostname(host||"localhost", family, display_id)
413
532
 
414
- auth_name, auth_data = auth_info.auth_name, auth_info.auth_data
533
+ if auth_info
534
+ auth_name, auth_data = auth_info.auth_name, auth_info.auth_data
535
+ else
536
+ auth_name = ""
537
+ auth_data = ""
538
+ end
415
539
  p [auth_name, auth_data]
416
540
 
417
541
  handshake = Form::ClientHandshake.new(
data/lib/X11/form.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'ostruct'
2
1
 
3
2
  module X11
4
3
  module Form
@@ -332,14 +331,26 @@ module X11
332
331
  InputOutput = 1
333
332
  InputOnly = 2
334
333
 
335
- CWBackPixel = 0x0002
334
+ CWBackPixmap = 0x0001
335
+ CWBackPixel = 0x0002
336
+ CWBorderPixmap= 0x0004
336
337
  CWBorderPixel = 0x0008
337
- CWEventMask = 0x0800
338
- CWColorMap = 0x2000
338
+ CWBitGravity = 0x0010
339
+ CWWinGravity = 0x0020
340
+ CWBackingStore= 0x0040
341
+ CWSaveUnder = 0x0400
342
+ CWEventMask = 0x0800
343
+ CWColorMap = 0x2000
339
344
 
340
345
  KeyPressMask = 0x00001
346
+ KeyReleaseMask = 0x00002
341
347
  ButtonPressMask = 0x00004
348
+ ButtonReleaseMask = 0x00008
349
+ EnterWindowMask = 0x00010
350
+ LeaveWindowMask = 0x00020
342
351
  PointerMotionMask = 0x00040
352
+ PointerMotionHintMask = 0x00080
353
+ Button1MotionMask = 0x00100
343
354
  ExposureMask = 0x08000
344
355
  StructureNotifyMask = 0x20000
345
356
  SubstructureNotifyMask = 0x80000
@@ -361,6 +372,51 @@ module X11
361
372
  field :value_list, Uint32, :list
362
373
  end
363
374
 
375
+ class ChangeWindowAttributes < BaseForm
376
+ field :opcode, Uint8, value: 2
377
+ unused 1
378
+ field :request_length, Uint16, value: ->(cw) { 3 + cw.value_list.length }
379
+ field :window, Window
380
+ field :value_mask, Bitmask
381
+ field :value_list, Uint32, :list
382
+ end
383
+
384
+ class GetWindowAttributes < BaseForm
385
+ field :opcode, Uint8, value: 3
386
+ unused 1
387
+ field :request_length, Uint16, value: 2
388
+ field :window, Window
389
+ end
390
+
391
+ class WindowAttributes < BaseForm
392
+ field :reply, Uint8, value: 1
393
+ field :backing_store, Uint8
394
+ field :sequence_number, Uint16
395
+ field :reply_length, Uint32
396
+ field :visual, VisualID
397
+ field :class, Uint16
398
+ field :bit_gravity, Uint8
399
+ field :win_gravity, Uint8
400
+ field :backing_planes, Uint32
401
+ field :backing_pixel, Uint32
402
+ field :save_under, Bool
403
+ field :map_is_installed, Bool
404
+ field :map_state, Bool
405
+ field :override_redirect, Bool
406
+ field :colormap, Colormap
407
+ field :all_event_masks, Uint32
408
+ field :your_event_masks, Uint32
409
+ field :do_not_propagate_mask, Uint16
410
+ unused 2
411
+ end
412
+
413
+ class DestroyWindow < BaseForm
414
+ field :opcode, Uint8, value: 4
415
+ unused 1
416
+ field :request_length, Uint16, value: 2
417
+ field :window, Window
418
+ end
419
+
364
420
  class MapWindow < BaseForm
365
421
  field :opcode, Uint8, value: 8
366
422
  unused 1
@@ -368,6 +424,37 @@ module X11
368
424
  field :window, Window
369
425
  end
370
426
 
427
+ class ConfigureWindow < BaseForm
428
+ field :opcode, Uint8, value: 12
429
+ unused 1
430
+ field :request_length, Uint16, value: ->(cw) { 3 + cw.values.length }
431
+ field :window, Window
432
+ field :value_mask, Uint16
433
+ unused 2
434
+ field :values, Uint32, :list
435
+ end
436
+
437
+ class GetGeometry < BaseForm
438
+ field :opcode, Uint8, value: 14
439
+ unused 1
440
+ field :request_length, Uint16, value: 2
441
+ field :drawable, Drawable
442
+ end
443
+
444
+ class Geometry < BaseForm
445
+ field :reply, Uint8, value: 1
446
+ field :depth, Uint8
447
+ field :sequence_number, Uint16
448
+ field :reply_length, Uint32
449
+ field :root, Window
450
+ field :x, Int16
451
+ field :y, Int16
452
+ field :width, Uint16
453
+ field :height, Uint16
454
+ field :border_width, Uint16
455
+ unused 10
456
+ end
457
+
371
458
  class InternAtom < BaseForm
372
459
  field :opcode, Uint8, value: 16
373
460
  field :only_if_exists, Bool
@@ -415,16 +502,31 @@ module X11
415
502
  field :data, Uint8, :list
416
503
  end
417
504
 
418
- class OpenFont < BaseForm
419
- field :opcode, Uint8, value: 45
505
+ class GrabButton < BaseForm
506
+ field :opcode, Uint8, value: 28
507
+ field :owner_events, Bool
508
+ field :request_length, Uint16, value: 6
509
+ field :grab_window, Window
510
+ field :event_mask, Uint16
511
+ field :pointer_mode, Uint8
512
+ field :keyboard_mode, Uint8
513
+ field :confine_to, Window
514
+ field :cursor, Cursor
515
+ field :button, Uint8
420
516
  unused 1
421
- field :request_length, Uint16, value: ->(of) {
422
- 3+(of.name.length+3)/4
423
- }
424
- field :fid, Font
425
- field :name, Uint16, :length
426
- unused 2
427
- field :name, String8, :string
517
+ field :modifiers, Uint16
518
+ end
519
+
520
+ class GrabKey < BaseForm
521
+ field :opcode, Uint8, value: 33
522
+ field :owner_event, Bool
523
+ field :request_length, Uint16, value: 4
524
+ field :grab_window, Window
525
+ field :modifiers, Uint16
526
+ field :keycode, Uint8
527
+ field :pointer_mode, Uint8
528
+ field :keyboard_mode, Uint8
529
+ unused 3
428
530
  end
429
531
 
430
532
  class ListFonts < BaseForm
@@ -677,6 +779,9 @@ module X11
677
779
 
678
780
  class MotionNotify < PressEvent
679
781
  end
782
+
783
+ class ButtonRelease < PressEvent
784
+ end
680
785
 
681
786
  class Expose < SimpleEvent
682
787
  field :window, Window
data/lib/X11/keysyms.rb CHANGED
@@ -114,13 +114,18 @@ module X11
114
114
  0xff9d => :XK_KP_Begin,
115
115
  0xff9e => :XK_KP_Insert,
116
116
  0xff9f => :XK_KP_Delete,
117
- 0xffbd => :XK_KP_Equal,
118
117
  0xffaa => :XK_KP_Multiply,
119
118
  0xffab => :XK_KP_Add,
120
119
  0xffac => :XK_KP_Separator,
121
120
  0xffad => :XK_KP_Subtract,
122
121
  0xffae => :XK_KP_Decimal,
123
122
  0xffaf => :XK_KP_Divide,
123
+ 0xffbd => :XK_KP_Equal,
124
+ 0xffbe => :f1,
125
+ 0xffbf => :f2,
126
+ 0xffc0 => :f3,
127
+ 0xffc1 => :f4, # And so on
128
+
124
129
 
125
130
  0xffe1 => :XK_Shift_L,
126
131
  0xffe2 => :XK_Shift_R,
data/lib/X11/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module X11
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.4"
3
3
  end
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.2
4
+ version: 0.0.4
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: 2023-09-25 00:00:00.000000000 Z
12
+ date: 2023-11-21 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Pure Ruby X11 bindings
15
15
  email: