atspi 0.8.0

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