Class: ATSPI::Accessible::Descendants

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/atspi/accessible/descendants.rb,
lib/atspi/accessible/descendants/options.rb,
lib/atspi/accessible/descendants/name_filter.rb,
lib/atspi/accessible/descendants/role_filter.rb,
lib/atspi/accessible/descendants/state_filter.rb,
lib/atspi/accessible/descendants/attribute_filter.rb,
lib/atspi/accessible/descendants/interface_filter.rb

Overview

A collection of all descendants in the tree below the accessible it belongs to. It can be filtered by state, attribute, role, interface and name using #where. The number of descendants to return can be set by #limit_to. Recursive search of the tree can be turned on and off by #recursive.

All methods can be chained together:

descendants = ATSPI.applications.first.descendants
descendants.where(role: :page_tab, state: :selected).recursive(false).limit_to(1)
# => #<ATSPI::Accessible::Descendants:0x101c51014 @state=all:[:selected] @role=any:[:page_tab] @limit=1 @recursive?=false … >

To get the actual collection as an array call #to_a. Methods not defined here are automatically delegated to #to_a, so instances of this class can be directly treated like an array.

descendants.where(interface: :Action).map{ |d| d.actions.map(&:name) }
# => [["click"], [], ["click"], [], …]

In essence, it wraps libatspi’s AtspiCollection and AtspiMatchRule

Filter collapse

Options collapse

Access collapse

Selection collapse

Representations collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object

Delegates missing methods to #to_a

Returns:

  • (Object)

    whatever Array#__send__(m, *args, &block) returns



264
265
266
# File 'lib/atspi/accessible/descendants.rb', line 264

def method_missing(m, *args, &block)
  to_a.__send__(m, *args, &block)
end

Instance Method Details

#deselect_alltrue, false

Tries to deselect all descendants in the collection

Returns:

  • (true, false)

    indicates if all are now deselected



285
286
287
# File 'lib/atspi/accessible/descendants.rb', line 285

def deselect_all
  map(&:deselect).all?
end

#inspectString

Returns itself as an inspectable string.

Returns:

  • (String)

    itself as an inspectable string



292
293
294
295
# File 'lib/atspi/accessible/descendants.rb', line 292

def inspect
  filter_inspect = @filters.map{ |n,f| "@#{n}=#{f.inspect}" }.join(' ')
  "#<#{self.class.name}:0x#{'%x14' % __id__} #{filter_inspect} #{@options.inspect}>"
end

#invert(invert = true) ⇒ Descendants

Note:

Seems to be not considered by libatspi?!

Inverts the conditions set by #where.

Parameters:

  • invert (true, false) (defaults to: true)

Returns:

  • (Descendants)

    a copy of the current descendants with the modified inverted option.

See Also:



199
200
201
# File 'lib/atspi/accessible/descendants.rb', line 199

def invert(invert = true)
  dup(options: @options.invert(invert))
end

#limit_to(limit) ⇒ Descendants

Limits the number of descendants to return.

Parameters:

  • limit (Integer)

    A value of 0 disables the limit.

Returns:

  • (Descendants)

    a copy of the current descendants with the modified limit option.

See Also:



229
230
231
# File 'lib/atspi/accessible/descendants.rb', line 229

def limit_to(limit)
  dup(options: @options.limit_to(limit))
end

#recursive(recursive = true) ⇒ Descendants

Turns recursive search on and off.

Parameters:

  • recursive (true, false) (defaults to: true)

    To limit the descendants to the direct children of the accessible only, set recursive to false. By setting recursive to true, all descendants in the tree below the accessible the descendants are considered.

Returns:

  • (Descendants)

    a copy of the current descendants with the modified recursive option.

See Also:



244
245
246
# File 'lib/atspi/accessible/descendants.rb', line 244

def recursive(recursive = true)
  dup(options: @options.recursive(recursive))
end

#select_alltrue, false

Tries to select all descendants in the collection

Returns:

  • (true, false)

    indicates if all are now selected



278
279
280
# File 'lib/atspi/accessible/descendants.rb', line 278

def select_all
  map(&:select).all?
end

#selectedArray<Accessible>

Returns its selected subset.

Returns:



271
272
273
# File 'lib/atspi/accessible/descendants.rb', line 271

def selected
  select(&:selected?)
end

#sort_by(order) ⇒ Descendants

Sorts the collection of descendants.

Examples:

descendants.sort_by(:flow) # => #<ATSPI::Accessible::Descendants:0x101c51014 … >

Parameters:

  • order (Symbol)

    derived from libatspi’s AtspiCollectionSortOrder enum by removing the prefix ATSPI_Collection_SORT_ORDER_ and making it lowercase.

Returns:

  • (Descendants)

    a copy of the current descendants with the modified order option.

See Also:



217
218
219
# File 'lib/atspi/accessible/descendants.rb', line 217

def sort_by(order)
  dup(options: @options.order_by(order))
end

#to_aArray<Accessible>

Returns the descendants according to the configured filters and options. The collection will be empty if the accessible does not implement the collection interface.

Returns:

  • (Array<Accessible>)

    the descendants according to the configured filters and options. The collection will be empty if the accessible does not implement the collection interface



253
254
255
256
257
258
259
260
# File 'lib/atspi/accessible/descendants.rb', line 253

def to_a
  return [] unless @native.collection_iface
  match_rule = Libatspi::MatchRule.new(*@filters[:state], *@filters[:attributes],
    *@filters[:role], *@filters[:interface], @options.inverted?)
  matches = @native.matches(match_rule, *@options).to_a
  matches = matches.select{ |native| native.name =~ @filters[:name].match } if @filters[:name].match
  matches.map{ |native| Accessible.new(native) }
end

#where(state: ) ⇒ Descendants #where(attributes: ) ⇒ Descendants #where(role: ) ⇒ Descendants #where(interface: ) ⇒ Descendants #where(name: ) ⇒ Descendants #where(filters) ⇒ Descendants

Note:

Filtering sometimes felt rocky on libatspi’s side during testing. See the notes in the following sections for details.

Returns a copy of this instance with the modified filters.

Overloads:

  • #where(state: ) ⇒ Descendants

    Filters by state(s)

    Examples:

    # Selects accessibles in state :selected
    where(state: :selected)
    
    # Selects accessibles in both states :selectable *and* :selected
    where(state: [:selectable, :selected])
    
    # Selects accessibles in either state :selectable *or* :selected (or both)
    where(state: [:selectable, :selected, mode: :any])

    Parameters:

    • state (Symbol, Array<Symbol[, mode: :all]>) (defaults to: )

      the states filter. States are given as symbol derived from libatspi’s AtspiStateType enum by removing the ATSPI_STATE_ prefix and making it lowercase.

      When given an array, the last item can be set to a hash configuring the filter mode. The mode has to be one of :all, :any, :none, :empty. It corresponds to the match type in atspi_match_rule_new and AtspiCollectionMatchType, accordingly.

  • #where(attributes: ) ⇒ Descendants
    Note:

    Filtering attributes in mode :all effectively disables the filter and returns all descendants. It does not narrow down the result set as one would expect.

    Filters by attribute(s)

    Examples:

    # Selects accessibles with value "button" for attribute "tag"
    where(attributes: { "tag" => "button" })
    
    # Selects accessibles with value "button" *or* "input" for attribute "tag"
    where(attributes: { "tag" => ["button", "input"] })
    
    # Selects accessibles with value "button" for attribute "tag" *or* value "block" for attribute "display"
    where(attributes: { "tag" => "button", "display" => "block" })

    Parameters:

    • attributes (Hash<String => String[, mode: :any]>) (defaults to: )

      the attributes filter. Attributes are given as a Hash as returned by ATSPI::Accessible#attributes.

      The :mode key of the hash can be used to configuring the filter mode. The mode has to be one of :all, :any, :none, :empty. It corresponds to the match type in atspi_match_rule_new and AtspiCollectionMatchType, accordingly.

  • #where(role: ) ⇒ Descendants
    Note:

    Setting the mode to a value different from :any for role filters effectively disables the filter and returns all descendants. Since an accessible has only exactly one role, one would expect that it does return an empty set, but it does not.

    Filters by role

    Examples:

    # Selects accessibles with role :frame
    where(role: :frame)
    
    # Selects accessibles with role :page_tab_list *or* :page_tab
    where(role: [:page_tab_list, :page_tab])

    Parameters:

    • role (Symbol, Array<Symbol[, mode: :any]>) (defaults to: )

      the roles filter. Roles are given as symbols derived from libatspi’s AtspiRole enum by removing the ATSPI_ROLE_ prefix and making it lowercase.

      When given an array, the last item can be set to a hash configuring the filter mode. The mode has to be one of :all, :any, :none, :empty. It corresponds to the match type in atspi_match_rule_new and AtspiCollectionMatchType, accordingly.

  • #where(interface: ) ⇒ Descendants
    Note:

    Filtering by multiple interfaces and including :Accessible or :Collection in mode :all does not work. Instead it always returns an empty set.

    Note:

    Filtering interfaces in mode :none effectively disables the filter and returns the entire set of descendants. Since an accessible always has at least the accessible interfaces it implements one would expect that it does return an empty set, but it does not.

    Filters by interface(s)

    Examples:

    # Selects accessibles implementing Action
    where(interface: :Action)
    
    # Selects accessibles implementing Action+ *and* Selection
    where(interface: [:Action, :Selection])
    
    # Selects accessibles implementing Action *or* +Selection or both
    where(interface: [:Action, :Selection, mode: :any])

    Parameters:

    • role (Symbol, Array<Symbol[, mode: :all]>)

      the role filter. Interfaces are given as symbols derived from their name returned by ATSPI::Accessible#interfaces

      When given an array, the last item can be set to a hash configuring the filter mode. The mode has to be one of :all, :any, :none, :empty. It corresponds to the match type in atspi_match_rule_new and AtspiCollectionMatchType, accordingly.

  • #where(name: ) ⇒ Descendants

    Filters by name

    Examples:

    # Selects accessibles with name exactly "Accessibles Name"
    where(name: "Accessible Name")
    
    # Selects accessibles with a name matching /a.{11}y/
    where(name: /a.{11}y/)

    Parameters:

    • name (String, RegExp) (defaults to: )

      the name filter. When given a string it is matched against the entire name from start to end like /^name$/.

  • #where(filters) ⇒ Descendants

    Combines all or a subset of filters in a single call.

    Examples:

    where(name: /a.{11}y/, state: [:selectable, :selected], role: :page_tab)

    Parameters:

    • filters (Hash)

    Options Hash (filters):

    • :states (Symbol, Array)
    • :role (Symbol, Array)
    • :name (String, RegExp)
    • :attributes (Hash)
    • :interface (Symbol, Array)

Returns:

  • (Descendants)

    a copy of this instance with the modified filters.

See Also:



182
183
184
185
186
187
# File 'lib/atspi/accessible/descendants.rb', line 182

def where(filters)
  dup(filters: @filters.map do |name, filter|
    extended_filter = filters[name] ? filter.extend(*filters[name]) : filter
    [name, extended_filter]
  end.to_h)
end