xkbcommon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a33e1dab78a94efb73575ca12f53fc05b456699c
4
+ data.tar.gz: ae8dce5f97d43acc6548c5a8f94338d7510a54c6
5
+ SHA512:
6
+ metadata.gz: 237bad6821313b087c490928cb8dd0c9871594a65ea6c2ab115380d8c9c7f11bfed8376da53a5cda3190d8e2ebb07a6149fad2b012ffd1a01268c7047fa22f15
7
+ data.tar.gz: c88eeb0d8ef13831d705db505cbae076be058cfcbfba27c984ad2b42551b3840de11d797ce9fd6fc25bd13f45a0d3b3053f1c6f09d87196c87f7dd10cc1ad501
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Settings><!--This file was automatically generated by Ruby plugin.
3
+ You are allowed to:
4
+ 1. Remove rake task
5
+ 2. Add existing rake tasks
6
+ To add existing rake tasks automatically delete this file and reload the project.
7
+ --><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build xkbcommon-0.1.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Build and install xkbcommon-0.1.0.gem into system gems" fullCmd="install" taksId="install" /><RakeTask description="Create tag v0.1.0 and build and push xkbcommon-0.1.0.gem to Rubygems" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'libxkbcommon', path: '../ruby-libxkbcommon'
5
+ gem 'uinput', path: '../ruby-uinput'
@@ -0,0 +1,63 @@
1
+ # Xkbcommon
2
+
3
+ xkbcommon bindings for ruby
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'xkbcommon'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install xkbcommon
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'xkbcommon'
25
+
26
+ keymap = Xkbcommon::Context.new.keymap_from_names(rules: 'evdev', model: 'pc104', layout: 'de', variant: 'nodeadkeys')
27
+
28
+ # Available keys in keymap
29
+ keymap.keys # => [ #<Xkbcommon::Key>, #<Xkbcommon::Key>, ... ]
30
+
31
+ # Xkbcommon::Key interface
32
+ key = keymap.keys.find{ |key| key.name == :A }
33
+ key.name # => :A
34
+ key.scan_code # => 30
35
+ key.code # => 38
36
+
37
+
38
+ # Available modifiers in keymap
39
+ keymap.modifiers # => [ #<Xkbcommon::Modifier>, #<Xkbcommon::Modifier>, ... ]
40
+
41
+ # Xkbcommon::Modifier interface
42
+ mod = keymap.modifiers.first
43
+ mod.name # => :Shift
44
+ mod.index # => 0
45
+ mod.keys.map(&:name) # => [:LEFTSHIFT], keys activating the modifier
46
+
47
+
48
+ # Available symbols in keymap
49
+ keymap.symbols # => { :Escape => #<Xkbcommon::Symbol>, :"1" => #<Xkbcommon::Symbol>, ... }
50
+
51
+ # Xkbcommon::Symbol interface
52
+ sym = keymap.symbols[:A]
53
+ sym.keysym # => 65
54
+ sym..keys.map(&:name) # => [:LEFTSHIFT, :A], keys producing the symbol
55
+ sym.name # => :A
56
+ sym.character # => "A"
57
+
58
+
59
+ # Available characters in keymap
60
+ keymap.characters # => { "\e" => #<Xkbcommon::Symbol>, "1" => #<Xkbcommon::Symbol>, ... }
61
+
62
+ # Xkbcommon::Symbol interface (see above)
63
+ ```
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,10 @@
1
+ require 'libxkbcommon'
2
+ require "xkbcommon/version"
3
+
4
+ require "xkbcommon/context"
5
+ require "xkbcommon/keymap"
6
+ require "xkbcommon/keymap/parser"
7
+ require "xkbcommon/key"
8
+ require "xkbcommon/symbol"
9
+ require "xkbcommon/modifier"
10
+ require "xkbcommon/state"
@@ -0,0 +1,52 @@
1
+ module Xkbcommon
2
+ class Context
3
+ class << self
4
+ def finalize(native)
5
+ Proc.new { Libxkbcommon.xkb_context_unref(native) }
6
+ end
7
+ end
8
+
9
+ def initialize(flags = Libxkbcommon::XKB_CONTEXT_NO_FLAGS)
10
+ @to_native = Libxkbcommon.xkb_context_new(flags)
11
+
12
+ ObjectSpace.define_finalizer(self, self.class.finalize(to_native))
13
+ end
14
+
15
+ attr_reader :to_native
16
+
17
+ def default_keymap
18
+ keymap_from_names
19
+ end
20
+
21
+ def keymap_from_names(rules: nil, model: nil, layout: nil, variant: nil, options: nil,
22
+ flags: Libxkbcommon::XKB_KEYMAP_COMPILE_NO_FLAGS)
23
+ names = Libxkbcommon::XkbRuleNames.new
24
+ names.rules = rules if rules
25
+ names.model = model if model
26
+ names.layout = layout if layout
27
+ names.variant = variant if variant
28
+ names.options = options if options
29
+
30
+ Keymap.new(self, Libxkbcommon.xkb_keymap_new_from_names(to_native, names, flags))
31
+ end
32
+
33
+ def keymap_from_file(file,
34
+ format: Libxkbcommon::XKB_KEYMAP_FORMAT_TEXT_V1,
35
+ flags: Libxkbcommon::XKB_KEYMAP_COMPILE_NO_FLAGS)
36
+ Keymap.new(self, Libxkbcommon.xkb_keymap_new_from_file(to_native, file, format, flags))
37
+ end
38
+
39
+ def keymap_from_string(string,
40
+ format: Libxkbcommon::XKB_KEYMAP_FORMAT_TEXT_V1,
41
+ flags: Libxkbcommon::XKB_KEYMAP_COMPILE_NO_FLAGS)
42
+ Keymap.new(self, Libxkbcommon.xkb_keymap_new_from_string(to_native, string, format, flags))
43
+ end
44
+
45
+ def keymap_from_buffer(buffer,
46
+ length,
47
+ format: Libxkbcommon::XKB_KEYMAP_FORMAT_TEXT_V1,
48
+ flags: Libxkbcommon::XKB_KEYMAP_COMPILE_NO_FLAGS)
49
+ Keymap.new(self, Libxkbcommon.xkb_keymap_new_from_buffer(to_native, buffer, length, format, flags))
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,34 @@
1
+ require 'uinput'
2
+
3
+ module Xkbcommon
4
+ class Key
5
+ class << self
6
+ def code_to_name(code)
7
+ codes_to_names[code]
8
+ end
9
+
10
+ private
11
+
12
+ def codes_to_names
13
+ @names ||= begin
14
+ keys = Uinput.constants.select{ |c| c.to_s.start_with?('KEY_') }
15
+ keys.map do |c|
16
+ code = Uinput.const_get(c)
17
+ name = c.to_s[4..-1]
18
+ name = Integer(name) rescue name.to_sym
19
+ [code, name]
20
+ end.to_h
21
+ end
22
+ end
23
+ end
24
+
25
+ def initialize(keymap, code)
26
+ @keymap = keymap
27
+ @code = code
28
+ @scan_code = code - 8 # about offset 8: http://xkbcommon.org/doc/current/xkbcommon_8h.html#ac29aee92124c08d1953910ab28ee1997
29
+ @name = self.class.code_to_name(@scan_code)
30
+ end
31
+
32
+ attr_reader :keymap, :code, :scan_code, :name
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ require 'forwardable'
2
+
3
+ module Xkbcommon
4
+ class Keymap
5
+ extend Forwardable
6
+
7
+ class << self
8
+ def finalize(native)
9
+ Proc.new { Libxkbcommon.xkb_keymap_unref(native) }
10
+ end
11
+ end
12
+
13
+ def initialize(context, keymap)
14
+ @context = context
15
+ @to_native = keymap
16
+ @parser = Parser.new(self)
17
+
18
+ ObjectSpace.define_finalizer(self, self.class.finalize(to_native))
19
+ end
20
+
21
+ attr_reader :context, :to_native
22
+ delegate [:keys, :modifiers, :symbols, :characters] => :@parser
23
+
24
+ def to_s(format: Libxkbcommon::XKB_KEYMAP_USE_ORIGINAL_FORMAT)
25
+ Libxkbcommon.xkb_keymap_get_as_string(to_native, format)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,109 @@
1
+ module Xkbcommon
2
+ class Keymap
3
+ class Parser
4
+ def initialize(keymap)
5
+ @keymap = keymap
6
+ end
7
+
8
+ attr_reader :keymap
9
+
10
+ def keys
11
+ @keys ||= begin
12
+ min_code = Libxkbcommon.xkb_keymap_min_keycode(@keymap.to_native)
13
+ max_code = Libxkbcommon.xkb_keymap_max_keycode(@keymap.to_native)
14
+ keycode_range = min_code..max_code
15
+
16
+ codes = keycode_range.select do |code|
17
+ # Todo: This does not seem to filter out keys that do not exist on the keyboard?
18
+ 0 < Libxkbcommon.xkb_keymap_num_layouts_for_key(@keymap.to_native, code)
19
+ end
20
+ codes.map{ |code| Key.new(self, code) }
21
+ end
22
+ end
23
+
24
+ def modifiers
25
+ symbols # will be parsed while parsing symbols
26
+ @modifiers
27
+ end
28
+
29
+ def symbols
30
+ @symbols ||= begin
31
+ symbols = parse_symbols
32
+ # first parse round will give us all modifier keys, so we can parse
33
+ # what keys active which modifiers next
34
+
35
+ @modifiers = parse_modifiers(symbols)
36
+
37
+ all_combinations(@modifiers).each do |modifiers|
38
+ symbols = parse_symbols(symbols, modifiers)
39
+ end
40
+
41
+ symbols
42
+ end
43
+ end
44
+
45
+ def characters
46
+ symbols # will be parsed while parsing symbols
47
+ @characters
48
+ end
49
+
50
+ private
51
+
52
+ def parse_symbols(symbols = {}, modifiers = [])
53
+ state = Xkbcommon::State.new(@keymap)
54
+ modifier_mask = modifiers.map{ |mod| 1 << mod.index }.reduce(0, :|)
55
+ state.update_mask(depressed_mods: modifier_mask)
56
+
57
+ keys.each do |key|
58
+ symbol = state.symbol_for_key(key)
59
+ if symbol
60
+ symbol.keys = [modifiers.map(&:keys), key].flatten
61
+ # We just need one key combo to create the symbol. The first should be the simplest,
62
+ # we take that one.
63
+ symbols[symbol.name] ||= symbol
64
+ if symbol.character
65
+ @characters ||= {}
66
+ # We just need one key combo to create the character. The first should be the simplest,
67
+ # we take that one.
68
+ @characters[symbol.character] ||= symbol
69
+ end
70
+ end
71
+ end
72
+
73
+ symbols
74
+ end
75
+
76
+ def parse_modifiers(symbols)
77
+ modifier_count = Libxkbcommon.xkb_keymap_num_mods(@keymap.to_native)
78
+ not_activated_modifiers = (0..modifier_count-1).map{ |idx| Modifier.new(@keymap, idx) }
79
+ activated_modifiers = []
80
+
81
+ state = Xkbcommon::State.new(@keymap)
82
+
83
+ modifier_keys = Modifier::SYMBOLS.select{ |sym| symbols[sym] }.map{ |sym| symbols[sym].keys }
84
+ modifier_keys.each do |keys|
85
+ new_state_components = state.press_keys(keys) || 0
86
+
87
+ if new_state_components & Libxkbcommon::XKB_STATE_MODS_EFFECTIVE != 0
88
+ # Once we found a modifier and know how to activate it we no longer need to check it
89
+ newly_activated_modifiers = not_activated_modifiers.select{ |mod| state.modifier_active?(mod) }
90
+ newly_activated_modifiers.each{ |mod| mod.keys = keys }
91
+
92
+ not_activated_modifiers -= newly_activated_modifiers
93
+ activated_modifiers += newly_activated_modifiers
94
+ end
95
+
96
+ state.release_keys(keys)
97
+ end
98
+
99
+ activated_modifiers
100
+ end
101
+
102
+ def all_combinations(array)
103
+ 1.upto(array.size).inject([]) do |memo, group_size|
104
+ memo + array.combination(group_size).to_a
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,51 @@
1
+ module Xkbcommon
2
+ class Modifier
3
+ SYMBOLS = [
4
+ :Shift_L,
5
+ :Shift_R,
6
+ :Control_L,
7
+ :Control_R,
8
+ #:Caps_Lock,
9
+ #:Shift_Lock,
10
+ :Meta_L,
11
+ :Meta_R,
12
+ :Alt_L,
13
+ :Alt_R,
14
+ :Super_L,
15
+ :Super_R,
16
+ :Hyper_L,
17
+ :Hyper_R,
18
+ #:ISO_Lock,
19
+ :ISO_Level2_Latch,
20
+ :ISO_Level3_Shift,
21
+ :ISO_Level3_Latch,
22
+ #:ISO_Level3_Lock,
23
+ :ISO_Level5_Shift,
24
+ :ISO_Level5_Latch,
25
+ #:ISO_Level5_Lock,
26
+ :ISO_Group_Shift,
27
+ :ISO_Group_Latch,
28
+ #:ISO_Group_Lock,
29
+ :ISO_Next_Group,
30
+ #:ISO_Next_Group_Lock,
31
+ :ISO_Prev_Group,
32
+ #:ISO_Prev_Group_Lock,
33
+ :ISO_First_Group,
34
+ #:ISO_First_Group_Lock,
35
+ :ISO_Last_Group#,
36
+ #:ISO_Last_Group_Lock
37
+ ]
38
+
39
+ def initialize(keymap, index)
40
+ @keymap, @index = keymap, index
41
+ @name = Libxkbcommon.xkb_keymap_mod_get_name(keymap.to_native, index).to_sym
42
+ end
43
+
44
+ attr_reader :keymap, :index, :name, :keys
45
+
46
+ def keys=(keys)
47
+ return if @keys
48
+ @keys = [*keys].freeze
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,60 @@
1
+ module Xkbcommon
2
+ class State
3
+ class << self
4
+ def finalize(native)
5
+ Proc.new { Libxkbcommon.xkb_state_unref(native) }
6
+ end
7
+ end
8
+
9
+ def initialize(keymap)
10
+ @keymap = keymap
11
+ @to_native = Libxkbcommon.xkb_state_new(keymap.to_native)
12
+
13
+ ObjectSpace.define_finalizer(self, self.class.finalize(to_native))
14
+ end
15
+
16
+ attr_reader :keymap, :to_native
17
+
18
+ def update_mask(depressed_mods: 0,
19
+ latched_mods: 0,
20
+ locked_mods: 0,
21
+ depressed_layout: 0,
22
+ latched_layout: 0,
23
+ locked_layout: 0)
24
+ Libxkbcommon.xkb_state_update_mask(to_native, depressed_mods, latched_mods, locked_mods,
25
+ depressed_layout, latched_layout, locked_layout)
26
+ end
27
+
28
+ def press_key(key)
29
+ Libxkbcommon.xkb_state_update_key(to_native, key.code, Libxkbcommon::XKB_KEY_DOWN)
30
+ end
31
+
32
+ def press_keys(keys)
33
+ [*keys].map{ |key| press_key(key) }.last
34
+ end
35
+
36
+ def release_key(key)
37
+ Libxkbcommon.xkb_state_update_key(to_native, key.code, Libxkbcommon::XKB_KEY_UP)
38
+ end
39
+
40
+ def release_keys(keys)
41
+ [*keys].map{ |key| release_key(key) }.last
42
+ end
43
+
44
+ def utf8_of_key(key)
45
+ utf8_size = 8
46
+ utf8 = FFI::MemoryPointer.new(:char, utf8_size)
47
+ Libxkbcommon.xkb_state_key_get_utf8(to_native, key.code, utf8, utf8_size)
48
+ utf8.read_string.force_encoding('UTF-8')
49
+ end
50
+
51
+ def symbol_for_key(key)
52
+ keysym = Libxkbcommon.xkb_state_key_get_one_sym(to_native, key.code)
53
+ Symbol.new(@keymap, keysym) if keysym
54
+ end
55
+
56
+ def modifier_active?(modifier)
57
+ 0 < Libxkbcommon.xkb_state_mod_index_is_active(to_native, modifier.index, Libxkbcommon::XKB_STATE_MODS_EFFECTIVE)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,32 @@
1
+ module Xkbcommon
2
+ class Symbol
3
+ def initialize(keymap, keysym)
4
+ @keymap, @keysym = keymap, keysym
5
+ end
6
+
7
+ attr_reader :keymap, :keysym, :keys
8
+
9
+ def keys=(keys)
10
+ return if @keys
11
+ @keys = [*keys].freeze
12
+ end
13
+
14
+ def name
15
+ @name ||= begin
16
+ char_size = 64
17
+ char = FFI::MemoryPointer.new(:char, char_size)
18
+ Libxkbcommon.xkb_keysym_get_name(@keysym, char, char_size)
19
+ char.read_string.to_sym
20
+ end
21
+ end
22
+
23
+ def character
24
+ @character ||= begin
25
+ char_size = 8
26
+ char = FFI::MemoryPointer.new(:char, char_size)
27
+ Libxkbcommon.xkb_keysym_to_utf8(@keysym, char, char_size)
28
+ char.read_string.force_encoding('UTF-8')
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ module Xkbcommon
2
+ VERSION = "0.1.0"
3
+ end
data/test.rb ADDED
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ require 'bundler/setup'
3
+ require 'xkbcommon'
4
+
5
+ keymap = Xkbcommon::Context.new.keymap_from_names(rules: 'evdev', model: 'pc104', layout: 'de', variant: 'nodeadkeys')
6
+
7
+ def format_keys(keys)
8
+ keys.map{ |key| "#{key.name}(#{key.scan_code})" }
9
+ end
10
+
11
+ puts "KEYS"
12
+ puts format_keys(keymap.keys)
13
+ puts
14
+ puts "MODIFIERS"
15
+ puts keymap.modifiers.map{ |mod| "#{mod.name}: #{format_keys(mod.keys).join(' + ')}" }
16
+ puts
17
+ puts "SYMBOLS"
18
+ puts keymap.symbols.map{ |symbol_name, symbol| "#{symbol_name}: #{format_keys(symbol.keys).join(' + ')}" }
19
+ puts
20
+ puts "CHARACTERS"
21
+ puts keymap.characters.map{ |char, symbol| "#{char} #{char.bytes}: #{format_keys(symbol.keys).join(' + ')}" }
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'xkbcommon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "xkbcommon"
8
+ spec.version = Xkbcommon::VERSION
9
+ spec.authors = ["Christopher Aue"]
10
+ spec.email = ["mail@christopheraue.net"]
11
+
12
+ spec.summary = %q{xkbcommon bindings for ruby}
13
+ spec.homepage = "https://github.com/christopheraue/ruby-xkbcommon"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.8"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_dependency "libxkbcommon", "~> 1.0"
23
+ spec.add_dependency "uinput", "~> 1.0"
24
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xkbcommon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Aue
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: libxkbcommon
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: uinput
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ description:
70
+ email:
71
+ - mail@christopheraue.net
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rakeTasks"
78
+ - ".rspec"
79
+ - Gemfile
80
+ - README.md
81
+ - Rakefile
82
+ - lib/xkbcommon.rb
83
+ - lib/xkbcommon/context.rb
84
+ - lib/xkbcommon/key.rb
85
+ - lib/xkbcommon/keymap.rb
86
+ - lib/xkbcommon/keymap/parser.rb
87
+ - lib/xkbcommon/modifier.rb
88
+ - lib/xkbcommon/state.rb
89
+ - lib/xkbcommon/symbol.rb
90
+ - lib/xkbcommon/version.rb
91
+ - test.rb
92
+ - xkbcommon.gemspec
93
+ homepage: https://github.com/christopheraue/ruby-xkbcommon
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.8
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: xkbcommon bindings for ruby
117
+ test_files: []