pure-x11 0.0.14 → 0.0.15

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: bfea2e2042ed90f291727231b653878eb36f6f42b79dcdea63a247c912a663c3
4
- data.tar.gz: 0f1a025486ca695ed9941cf9061f082f1c3838cff15b4c559720f64d28b228b3
3
+ metadata.gz: 111eb03062f78f89280bc44425a4557b2f97527738d9d6fb93d0407f75050ff1
4
+ data.tar.gz: fbc1a6071fde31ed383b173dd45c8472c2ed1efa536037fd4d976d35a078e687
5
5
  SHA512:
6
- metadata.gz: d27618c1fb2c908ce4c9f2f4a4b7692f369d61ec968b7d9664f021cabc0fd032d7b8df11fb773631d49ce6d876c3eb75584c9bda28f4237bb581dc04b7928176
7
- data.tar.gz: 063be0a3b3dce1b4b15e57e2121b9c76ed5b65cac5369f9fc3032e133b8cd742d91907f94511d9805f6147d9f8b94b9a2d563e1645dcc94fd2cc507311b18133
6
+ metadata.gz: 02fc5f04906935f25afbd52443f1cc33b6d7f97bf95b145cf814adfc88ca8f1b1de635042d6c8854db2413b203af985076d25e7fbf7f8d1c6f92f904d9c5edd2
7
+ data.tar.gz: 8fe22103b7991e534d334d055325c0a93853878875af12bcfd5173720d1e05cf4ad484f69b4508ba2e84993a36176167ecbd29d64aa5481b6cf42c0e0f2c155c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pure-x11 (0.0.13)
4
+ pure-x11 (0.0.15)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/lib/X11/display.rb CHANGED
@@ -19,6 +19,10 @@ module X11
19
19
 
20
20
  # Open a connection to the specified display (numbered from 0) on the specified host
21
21
  def initialize(target = ENV['DISPLAY'])
22
+ # With no DISPLAY set (nil or empty), fall back to the conventional
23
+ # default display ":0" rather than letting the regex below leave host
24
+ # nil and crash on host.empty?.
25
+ target = ":0" if target.nil? || target.empty?
22
26
  target =~ /^([\w.-]*):(\d+)(?:.(\d+))?$/
23
27
  host, display_id, _screen_id = $1, $2, $3
24
28
  family = nil
@@ -495,6 +499,22 @@ module X11
495
499
  )
496
500
  end
497
501
 
502
+ # Actively grab the keyboard for grab_window. Returns the reply (status 0 =
503
+ # Success). Modes default to async so key events flow normally to the focus.
504
+ def grab_keyboard(grab_window, owner_events: true, pointer_mode: :async,
505
+ keyboard_mode: :async, time: 0)
506
+ write_sync(Form::GrabKeyboard.new(
507
+ owner_events ? 1 : 0,
508
+ grab_window, time,
509
+ pointer_mode == :async ? 1 : 0,
510
+ keyboard_mode == :async ? 1 : 0
511
+ ), Form::GrabKeyboardReply)
512
+ end
513
+
514
+ def ungrab_keyboard(time = 0)
515
+ write_request(Form::UngrabKeyboard.new(time))
516
+ end
517
+
498
518
  def set_value(values, mask, x)
499
519
  if x
500
520
  values << x
@@ -732,6 +752,10 @@ module X11
732
752
  write_sync(Form::QueryPointer.new(window), Form::QueryPointerReply)
733
753
  end
734
754
 
755
+ def get_input_focus
756
+ write_sync(Form::GetInputFocus.new, Form::GetInputFocusReply)
757
+ end
758
+
735
759
  private
736
760
 
737
761
  def authorize(host, family, display_id)
data/lib/X11/form.rb CHANGED
@@ -484,6 +484,20 @@ module X11
484
484
  unused 6
485
485
  end
486
486
 
487
+ class GetInputFocus < BaseForm
488
+ field :opcode, Uint8, value: 43
489
+ unused 1
490
+ field :request_length, Uint16, value: 1
491
+ end
492
+
493
+ class GetInputFocusReply < Reply
494
+ field :revert_to, Uint8
495
+ field :sequence_number, Uint16
496
+ field :reply_length, Uint32
497
+ field :focus, Window
498
+ unused 20
499
+ end
500
+
487
501
  class ChangeSaveSet < BaseForm
488
502
  field :opcode, Uint8, value: 6
489
503
  field :mode, Uint8
@@ -620,6 +634,10 @@ module X11
620
634
  unused 3
621
635
  field :data, Uint32, value: ->(cp) { cp.data.length / (cp.format/8) }
622
636
  field :data, Uint8, :list
637
+ # The protocol pads the data to a 4-byte boundary; request_length already
638
+ # accounts for it, so emit the pad bytes (otherwise format-8/16 data whose
639
+ # length isn't a multiple of 4 produces a short packet).
640
+ unused ->(cp) { (4 - cp.data.length % 4) % 4 }
623
641
  end
624
642
 
625
643
  class GetProperty < BaseForm
@@ -705,6 +723,31 @@ module X11
705
723
  unused 3
706
724
  end
707
725
 
726
+ class GrabKeyboard < BaseForm
727
+ field :opcode, Uint8, value: 31
728
+ field :owner_events, Bool
729
+ field :request_length, Uint16, value: 4
730
+ field :grab_window, Window
731
+ field :time, Uint32
732
+ field :pointer_mode, Uint8
733
+ field :keyboard_mode, Uint8
734
+ unused 2
735
+ end
736
+
737
+ class GrabKeyboardReply < Reply
738
+ field :status, Uint8
739
+ field :sequence_number, Uint16
740
+ field :reply_length, Uint32
741
+ unused 24
742
+ end
743
+
744
+ class UngrabKeyboard < BaseForm
745
+ field :opcode, Uint8, value: 32
746
+ unused 1
747
+ field :request_length, Uint16, value: 2
748
+ field :time, Uint32
749
+ end
750
+
708
751
  class OpenFont < BaseForm
709
752
  field :opcode, Uint8, value: 45
710
753
  unused 1
data/lib/X11/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module X11
2
- VERSION = "0.0.14"
2
+ VERSION = "0.0.15"
3
3
  end
data/lib/X11/window.rb CHANGED
@@ -24,6 +24,8 @@ module X11
24
24
  def get_property(...) = dpy.get_property(@wid,...)
25
25
  def grab_key(arg, ...) = dpy.grab_key(arg, @wid, ...)
26
26
  def grab_button(arg,...) = dpy.grab_button(arg, @wid, ...)
27
+ def grab_keyboard(...) = dpy.grab_keyboard(@wid, ...)
28
+ def ungrab_keyboard(...) = dpy.ungrab_keyboard(...)
27
29
  def change_property(mode, ...) = dpy.change_property(mode, @wid, ...)
28
30
  def set_input_focus(mode) = dpy.set_input_focus(mode, @wid)
29
31
  def select_input(...) = dpy.select_input(@wid,...)
data/test/core_test.rb CHANGED
@@ -11,5 +11,22 @@ describe X11 do
11
11
  expected = collection.size
12
12
  _(collection.uniq.size).must_equal expected
13
13
  end
14
+
15
+ it "falls back to :0 instead of crashing when DISPLAY is empty or unset" do
16
+ original = ENV["DISPLAY"]
17
+ ["", nil].each do |value|
18
+ value.nil? ? ENV.delete("DISPLAY") : ENV["DISPLAY"] = value
19
+ begin
20
+ X11::Display.new
21
+ rescue NoMethodError => e
22
+ flunk "DISPLAY=#{value.inspect} regressed to a crash: #{e.message}"
23
+ rescue StandardError
24
+ # A connection/socket error is fine here — the point is that parsing
25
+ # got past the empty DISPLAY and attempted the default display :0.
26
+ end
27
+ end
28
+ ensure
29
+ ENV["DISPLAY"] = original
30
+ end
14
31
  end
15
32
  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.14
4
+ version: 0.0.15
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-05-05 00:00:00.000000000 Z
12
+ date: 2026-06-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Pure Ruby X11 bindings
15
15
  email: