atspi 0.8.0

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.yardopts +2 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +69 -0
  7. data/Rakefile +2 -0
  8. data/atspi.gemspec +23 -0
  9. data/bin/console +7 -0
  10. data/lib/atspi/accessible/action.rb +45 -0
  11. data/lib/atspi/accessible/children/selected.rb +32 -0
  12. data/lib/atspi/accessible/children.rb +72 -0
  13. data/lib/atspi/accessible/descendants/attribute_filter.rb +32 -0
  14. data/lib/atspi/accessible/descendants/interface_filter.rb +24 -0
  15. data/lib/atspi/accessible/descendants/name_filter.rb +18 -0
  16. data/lib/atspi/accessible/descendants/options.rb +49 -0
  17. data/lib/atspi/accessible/descendants/role_filter.rb +23 -0
  18. data/lib/atspi/accessible/descendants/state_filter.rb +23 -0
  19. data/lib/atspi/accessible/descendants.rb +278 -0
  20. data/lib/atspi/accessible/document.rb +26 -0
  21. data/lib/atspi/accessible/extents.rb +129 -0
  22. data/lib/atspi/accessible/hyperlink/anchor.rb +30 -0
  23. data/lib/atspi/accessible/hyperlink.rb +31 -0
  24. data/lib/atspi/accessible/image.rb +35 -0
  25. data/lib/atspi/accessible/selectable.rb +47 -0
  26. data/lib/atspi/accessible/table/cell/columns.rb +44 -0
  27. data/lib/atspi/accessible/table/cell/rows.rb +44 -0
  28. data/lib/atspi/accessible/table/cell.rb +18 -0
  29. data/lib/atspi/accessible/table/cells.rb +37 -0
  30. data/lib/atspi/accessible/table/column.rb +59 -0
  31. data/lib/atspi/accessible/table/columns/selected.rb +42 -0
  32. data/lib/atspi/accessible/table/columns.rb +34 -0
  33. data/lib/atspi/accessible/table/row.rb +59 -0
  34. data/lib/atspi/accessible/table/rows/selected.rb +42 -0
  35. data/lib/atspi/accessible/table/rows.rb +31 -0
  36. data/lib/atspi/accessible/table.rb +50 -0
  37. data/lib/atspi/accessible/text/caret.rb +31 -0
  38. data/lib/atspi/accessible/text/character.rb +45 -0
  39. data/lib/atspi/accessible/text/editable.rb +90 -0
  40. data/lib/atspi/accessible/text/hyperlink.rb +19 -0
  41. data/lib/atspi/accessible/text/hypertext.rb +29 -0
  42. data/lib/atspi/accessible/text/offset.rb +59 -0
  43. data/lib/atspi/accessible/text/range.rb +66 -0
  44. data/lib/atspi/accessible/text/selection.rb +48 -0
  45. data/lib/atspi/accessible/text.rb +120 -0
  46. data/lib/atspi/accessible/value.rb +47 -0
  47. data/lib/atspi/accessible.rb +267 -0
  48. data/lib/atspi/application.rb +46 -0
  49. data/lib/atspi/collection.rb +60 -0
  50. data/lib/atspi/desktop.rb +52 -0
  51. data/lib/atspi/extents.rb +28 -0
  52. data/lib/atspi/libatspi.rb +7 -0
  53. data/lib/atspi/requires.rb +76 -0
  54. data/lib/atspi/selectable_collection/selected.rb +23 -0
  55. data/lib/atspi/selectable_collection.rb +32 -0
  56. data/lib/atspi/state_set.rb +141 -0
  57. data/lib/atspi/version.rb +4 -0
  58. data/lib/atspi/window.rb +33 -0
  59. data/lib/atspi.rb +58 -0
  60. metadata +132 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4d510b8f8cca6a7d67df7c04e3c485adb0af0866
4
+ data.tar.gz: a34a34c0cfd97aba0cb4c5b6bacfdee70cf0d9da
5
+ SHA512:
6
+ metadata.gz: 337d97b940e17119a553111369a2719ec1e6770d2b3d2b1ca4c6d6c8f716a6a1b746d5b55879e162f48870dfcc2975d8a43d7a641a01c3a4e29415630032fd42
7
+ data.tar.gz: 7f1e9c0f2192d285d74685b00348ded4e5caff5ddb8e8dbaa428e50a09d7fa344efc61c1ea4ee464a71e8898ff9cdc020f17711d8f4593cb371b7c6b9aa87cf4
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --embed-mixins
2
+ --hide-api private
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Christopher Aue
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Atspi
2
+
3
+ This is a ruby gem that lets you comfortably call the
4
+ [Assistive Technology Service Provider Interface](https://en.wikipedia.org/wiki/Assistive_Technology_Service_Provider_Interface)
5
+ on Linux.
6
+
7
+ It wraps Gnome's [libatspi](https://developer.gnome.org/libatspi/stable/) and
8
+ exposes it as high level ruby objects.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'atspi'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install atspi
25
+
26
+ ## Getting Started
27
+
28
+ ```ruby
29
+ # Get the desktop
30
+ desktop = ATSPI.desktops.first
31
+
32
+ # Get an application on the desktop (here Gnome Terminal)
33
+ application = desktop.applications.last
34
+
35
+ # Get the first window of the application
36
+ window = application.windows.first
37
+
38
+ # Get the window's tabs
39
+ tabs = window.descendants.where(role: :page_tab)
40
+ tabs.count # => 3
41
+
42
+ # Get the selected tab
43
+ selected_tab = tabs.where(state: :selected).first
44
+ selected_tab.index # => 0
45
+
46
+ # Select the first tab
47
+ tabs.last.select
48
+
49
+ # Get the selected tab
50
+ selected_tab = tabs.where(state: :selected).first
51
+ selected_tab.index # => 2
52
+ ```
53
+
54
+ ## Documentation
55
+
56
+ Detailed documentation can be found at [http://www.rubydoc.info/gems/atspi](http://www.rubydoc.info/gems/atspi).
57
+
58
+ Especially:
59
+
60
+ * Everything starts with the [ATSPI module](http://www.rubydoc.info/gems/atspi/ATSPI.html).
61
+ * Accessibles are represented by the [ATSPI::Accessible class](http://www.rubydoc.info/gems/atspi/ATSPI/Accessible.html).
62
+ + An accessible's descendants can be searched using the interface of the [ATSPI::Accessible::Descendants class](http://www.rubydoc.info/gems/atspi/ATSPI/Accessible/Descendants.html)
63
+
64
+ ## Todo
65
+
66
+ Not supported yet are:
67
+
68
+ * Event listeners
69
+ * (Editable) text attributes
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/atspi.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'atspi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "atspi"
8
+ spec.version = ATSPI::VERSION
9
+ spec.authors = ["Christopher Aue"]
10
+ spec.email = ["mail@christopheraue.net"]
11
+
12
+ spec.summary = %q{The atspi gem lets you comfortably call the Assistive Technology Service Provider Interface on Linux.}
13
+ spec.description = %q{It is a high level wrapper around libatspi.}
14
+ spec.homepage = "https://github.com/christopheraue/ruby-atspi"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "gir_ffi", "~> 0.10.0"
22
+ spec.add_development_dependency "bundler", "~> 1.8"
23
+ end
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "irb"
5
+ require "atspi"
6
+
7
+ IRB.start
@@ -0,0 +1,45 @@
1
+ class ATSPI::Accessible
2
+ # Wraps libatspi's AtspiAction[https://developer.gnome.org/libatspi/stable/libatspi-atspi-action.html]
3
+ class Action
4
+ # @api private
5
+ def initialize(native, idx)
6
+ @native = native
7
+ @idx = idx
8
+ end
9
+
10
+ # @return [String] its name
11
+ #
12
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-action.html#atspi-action-get-name atspi_action_get_name
13
+ def name
14
+ @native.action_name(@idx)
15
+ end
16
+
17
+ # @return [String] its description
18
+ #
19
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-action.html#atspi-action-get-description atspi_action_get_description
20
+ def description
21
+ @native.action_description(@idx)
22
+ end
23
+
24
+ # @return [String] its key binding
25
+ #
26
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-action.html#atspi-action-get-key-binding atspi_action_get_key_binding
27
+ def key_binding
28
+ @native.key_binding(@idx)
29
+ end
30
+
31
+ # Tries to execute the action
32
+ #
33
+ # @return [true,false] indicating success
34
+ #
35
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-action.html#atspi-action-do-action atspi_action_do_action
36
+ def do_it!
37
+ @native.do_action(@idx)
38
+ end
39
+
40
+ # @return [String] itself as an inspectable string
41
+ def inspect
42
+ "#<#{self.class.name}:0x#{'%x14' % __id__} @name=#{name.inspect} @description=#{description.inspect}>"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ module ATSPI
2
+ # Wraps libatspi's AtspiSelection[https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html]
3
+ # together with parts of {Selectable} and {Children}
4
+ class Accessible::Children::Selected
5
+ include SelectableCollection::Selected
6
+
7
+ # @api private
8
+ def initialize(native)
9
+ @native = native
10
+ end
11
+
12
+ # @!group Enumerable interface
13
+ # @param idx [Integer]
14
+ #
15
+ # @return [Accessible] its child at index +idx+
16
+ #
17
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html#atspi-selection-get-selected-child atspi_selection_get_selected_child
18
+ def at(idx)
19
+ super do |mapped_idx|
20
+ Accessible.new(@native.selected_child(mapped_idx))
21
+ end
22
+ end
23
+
24
+ # @return [Integer] its number of children
25
+ #
26
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html#atspi-selection-get-n-selected-children atspi_selection_get_n_selected_children
27
+ def count
28
+ @native.n_selected_children
29
+ end
30
+ # @!endgroup
31
+ end
32
+ end
@@ -0,0 +1,72 @@
1
+ module ATSPI
2
+ # Wraps the children part of libatspi's AtspiAccessible[https://developer.gnome.org/libatspi/stable/AtspiAccessible.html]
3
+ # and parts of AtspiSelection[https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html].
4
+ class Accessible::Children
5
+ include SelectableCollection
6
+
7
+ # @api private
8
+ def initialize(native)
9
+ @native = native
10
+ end
11
+
12
+ # @!group Enumerable interface
13
+ # @param idx [Integer]
14
+ #
15
+ # @return [Accessible] its child at index +idx+
16
+ #
17
+ # @see https://developer.gnome.org/libatspi/stable/AtspiAccessible.html#atspi-accessible-get-child-at-index atspi_accessible_get_child_at_index
18
+ def at(idx)
19
+ super do |mapped_idx|
20
+ Accessible.new(@native.child_at_index(mapped_idx))
21
+ end
22
+ end
23
+
24
+ # @return [Integer] its number of children
25
+ #
26
+ # @see https://developer.gnome.org/libatspi/stable/AtspiAccessible.html#atspi-accessible-get-child-count atspi_accessible_get_child_count
27
+ def count
28
+ @native.child_count
29
+ end
30
+ # @!endgroup
31
+
32
+ # @!group Selection
33
+ # Checks if the accessible the children belong to implements the selection
34
+ # interface.
35
+ #
36
+ # @return [true,false]
37
+ #
38
+ # @see https://developer.gnome.org/libatspi/stable/AtspiAccessible.html#atspi-accessible-get-selection atspi_accessible_get_selection
39
+ def selectable?
40
+ not @native.selection_iface.nil?
41
+ end
42
+
43
+ # @return [Selected,[]] its selected subset. It will be an empty array if
44
+ # children are not selectable.
45
+ def selected
46
+ if selectable?
47
+ Selected.new(@native)
48
+ else
49
+ []
50
+ end
51
+ end
52
+
53
+ # Tries to select all children
54
+ #
55
+ # @return [true,false] indicates success
56
+ #
57
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html#atspi-selection-select-all atspi_selection_select_all
58
+ def select_all
59
+ selectable? and @native.select_all
60
+ end
61
+
62
+ # Tries to deselect all children
63
+ #
64
+ # @return [true,false] indicates success
65
+ #
66
+ # @see https://developer.gnome.org/libatspi/stable/libatspi-atspi-selection.html#atspi-selection-clear-selection atspi_selection_clear_selection
67
+ def deselect_all
68
+ selectable? and @native.clear_selection
69
+ end
70
+ # @!endgroup
71
+ end
72
+ end
@@ -0,0 +1,32 @@
1
+ module ATSPI
2
+ class Accessible::Descendants
3
+ # @api private
4
+ class AttributeFilter
5
+ def initialize(mode: :any, attributes: {})
6
+ @mode = mode
7
+ @attributes = attributes
8
+ end
9
+
10
+ def extend(*attributes)
11
+ attributes = attributes.to_h
12
+ mode = attributes.delete(:mode) || @mode
13
+ attributes = attributes.inject(@attributes) do |memo, (key, values)|
14
+ memo.merge(key => [*memo[key], *values].uniq)
15
+ end
16
+ self.class.new(mode: mode, attributes: attributes)
17
+ end
18
+
19
+ def to_a
20
+ attributes = @attributes.map do |key, values|
21
+ escaped_values = values.map{ |value| value.gsub(':', '\:') }
22
+ [key, escaped_values.join('::')]
23
+ end.to_h
24
+ [attributes, @mode]
25
+ end
26
+
27
+ def inspect
28
+ "#{@mode}:#{@attributes.inspect}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ module ATSPI
2
+ class Accessible::Descendants
3
+ # @api private
4
+ class InterfaceFilter
5
+ def initialize(mode: :all, interfaces: [])
6
+ @mode = mode
7
+ @interfaces = interfaces
8
+ end
9
+
10
+ def extend(*interfaces, mode: @mode)
11
+ interfaces = @interfaces + interfaces.map(&:to_s)
12
+ self.class.new(mode: mode, interfaces: interfaces.uniq)
13
+ end
14
+
15
+ def to_a
16
+ [@interfaces.dup, @mode]
17
+ end
18
+
19
+ def inspect
20
+ "#{@mode}:#{@interfaces.inspect}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ class ATSPI::Accessible::Descendants
2
+ # @api private
3
+ class NameFilter
4
+ def initialize(match = nil)
5
+ @match = match
6
+ end
7
+
8
+ attr_reader :match
9
+
10
+ def extend(match)
11
+ self.class.new(match.is_a?(Regexp) ? match : /^#{Regexp.quote(match)}$/)
12
+ end
13
+
14
+ def inspect
15
+ @match.inspect
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,49 @@
1
+ class ATSPI::Accessible::Descendants
2
+ # @api private
3
+ class Options
4
+ def initialize(prototype = nil, extensions = {})
5
+ @prototype = prototype
6
+ @extensions = extensions
7
+ end
8
+
9
+ def invert(invert = true)
10
+ self.class.new(self, inverted?: invert)
11
+ end
12
+
13
+ def order_by(order)
14
+ self.class.new(self, order: order)
15
+ end
16
+
17
+ def limit_to(limit)
18
+ self.class.new(self, limit: limit)
19
+ end
20
+
21
+ def recursive(recursive = true)
22
+ self.class.new(self, recursive?: recursive)
23
+ end
24
+
25
+ def inverted?
26
+ @extensions.key?(:inverted?) ? @extensions[:inverted?] : @prototype.inverted?
27
+ end
28
+
29
+ def order
30
+ @extensions.key?(:order) ? @extensions[:order] : @prototype.order
31
+ end
32
+
33
+ def limit
34
+ @extensions.key?(:limit) ? @extensions[:limit] : @prototype.limit
35
+ end
36
+
37
+ def recursive?
38
+ @extensions.key?(:recursive?) ? @extensions[:recursive?] : @prototype.recursive?
39
+ end
40
+
41
+ def to_a
42
+ [order, limit, recursive?]
43
+ end
44
+
45
+ def inspect
46
+ "@inverted?=#{inverted?} @order=#{order} @limit=#{limit} @recursive?=#{recursive?}"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,23 @@
1
+ module ATSPI
2
+ class Accessible::Descendants
3
+ # @api private
4
+ class RoleFilter
5
+ def initialize(mode: :any, roles: [])
6
+ @mode = mode
7
+ @roles = roles
8
+ end
9
+
10
+ def extend(*roles, mode: @mode)
11
+ self.class.new(mode: mode, roles: (@roles + roles).uniq)
12
+ end
13
+
14
+ def to_a
15
+ [@roles.dup, @mode]
16
+ end
17
+
18
+ def inspect
19
+ "#{@mode}:#{@roles.inspect}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module ATSPI
2
+ class Accessible::Descendants
3
+ # @api private
4
+ class StateFilter
5
+ def initialize(mode: :all, states: [])
6
+ @mode = mode
7
+ @states = states
8
+ end
9
+
10
+ def extend(*states, mode: @mode)
11
+ self.class.new(mode: mode, states: (@states + states).uniq)
12
+ end
13
+
14
+ def to_a
15
+ [StateSet.new(*@states).__send__(:native), @mode]
16
+ end
17
+
18
+ def inspect
19
+ "#{@mode}:#{@states.inspect}"
20
+ end
21
+ end
22
+ end
23
+ end