pure-x11 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: