class AX::Application

The accessibility object representing the running application. This class contains some additional constructors and conveniences for Application objects.

As this class has evolved, it has gathered some functionality from the ‘NSRunningApplication` and `NSBundle` classes.

Public Class Methods

dock() click to toggle source

Find and return the dock application

@return [AX::Application]

# File lib/ax/application.rb, line 31
def dock
  new 'com.apple.dock'
end
finder() click to toggle source

Find and return the dock application

@return [AX::Application]

# File lib/ax/application.rb, line 39
def finder
  new 'com.apple.finder'
end
frontmost_app()
frontmost_application() click to toggle source

Find and return the application which is frontmost

This is often, but not necessarily, the same as the app that owns the menu bar.

@return [AX::Application]

# File lib/ax/application.rb, line 60
def frontmost_application
  new NSWorkspace.sharedWorkspace.frontmostApplication
end
Also aliased as: frontmost_app
launch(bundle) click to toggle source

Asynchronously launch an application with given the bundle identifier

@param bundle [String] bundle identifier for the app @return [Boolean]

# File lib/ax/application.rb, line 20
def launch bundle
  NSWorkspace.sharedWorkspace.launchAppWithBundleIdentifier bundle,
                                                   options: NSWorkspace::NSWorkspaceLaunchAsync,
                            additionalEventParamDescriptor: nil,
                                          launchIdentifier: nil
end
menu_bar_owner() click to toggle source

Find and return the application which owns the menu bar

This is often, but not necessarily, the same as the app that is frontmost.

@return [AX::Application]

new(arg) click to toggle source

@note Initialization with bundle identifiers is case-sensitive

(e.g. 'com.apple.iCal' is correct, 'com.apple.ical' is wrong)

Standard way of creating a new application object

You can initialize an application object with either the process identifier (pid) of the application, the name of the application, the bundle identifier string (e.g. ‘com.company.appName’), an ‘NSRunningApplication` instance for the application, or an accessibility (`AXUIElementRef`) token.

Given a PID, we try to lookup the application and wrap it.

Given an ‘NSRunningApplication` instance, we simply wrap it.

Given a string we do some complicated magic to try and figure out if the string is a bundle identifier or the localized name of the application. Given a bundle identifier we try to launch the app if it is not already running, given a localized name we search the running applications for the app. We wrap what we get back if we get anything back.

Note however, given a bundle identifier to launch the application our implementation is a bit of a hack; I’ve tried to register for notifications, launch synchronously, etc., but there is always a problem with accessibility not being ready right away, so we will poll the app to see when it is ready with a timeout of ~10 seconds.

If this method fails to find an app then an exception will be raised.

@example

AX::Application.new 'com.apple.mail'
AX::Application.new 'Mail'
AX::Application.new 578
AX::Application.new 'com.apple.iCal'
AX::Application.new 'Calendar'
AX::Application.new 3782
AX::Application.new 'com.apple.AddressBook'
AX::Application.new 'Contacts'
AX::Application.new 43567

@param arg [Number,String,NSRunningApplication]

Calls superclass method AX::Element::new
# File lib/ax/application.rb, line 121
def initialize arg
  @app = case arg
         when String
           init_with_bundle_id(arg) || init_with_name(arg) || try_launch(arg)
         when Fixnum
           NSRunningApplication.runningApplicationWithProcessIdentifier arg
         when NSRunningApplication
           arg
         else # assume it is an AXUIElementRef (Accessibility::Element)
           NSRunningApplication.runningApplicationWithProcessIdentifier arg.pid
         end
  super Accessibility::Element.application_for @app.processIdentifier
end
notification_center() click to toggle source

Find and return the notification center UI app

Obviously, this will only work on OS X 10.8+

@return [AX::Application]

# File lib/ax/application.rb, line 49
def notification_center
  new 'com.apple.notificationcenterui'
end

Public Instance Methods

active?() click to toggle source

Ask the app whether or not it is the active app. This is equivalent to the dynamic ‘#focused?` method, but might make more sense to use in some cases.

# File lib/ax/application.rb, line 159
def active?
  spin
  @app.active?
end
Also aliased as: focused, focused?
attribute(attr) click to toggle source

(see AX::Element#attribute)

Calls superclass method AX::Element#attribute
# File lib/ax/application.rb, line 139
def attribute attr
  case attr
  when :focused?, :focused then active?
  when :hidden?,  :hidden  then hidden?
  else super
  end
end
bundle_identifier() click to toggle source

Get the bundle identifier for the application.

@example

safari.bundle_identifier 'com.apple.safari'
daylite.bundle_identifier 'com.marketcircle.Daylite'

@return [String]

# File lib/ax/application.rb, line 201
def bundle_identifier
  @app.bundleIdentifier
end
element_at(point) click to toggle source

Find the element in the receiver that is at point given.

‘nil` will be returned if there was nothing at that point.

@param point [#to_point] @return [AX::Element,nil]

# File lib/ax/application.rb, line 416
def element_at point
  @ref.element_at(point).to_ruby
end
focused()
Alias for: active?
focused?()
Alias for: active?
hidden?() click to toggle source

Ask the app whether or not it is hidden.

# File lib/ax/application.rb, line 168
def hidden?
  spin
  @app.hidden?
end
hide() click to toggle source

@note This is often async and may return before the action is completed

Ask the app to hide itself

@return [Boolean]

# File lib/ax/application.rb, line 261
def hide
  perform :hide
end
hold_modifier(key) { || ... } click to toggle source

Press the given modifier key and hold it down while yielding to the given block. As with {#type}, the key events apply to the control element which is currently focused.

@example

hold_modifier "\\CONTROL" do
  drag_mouse_to point
end

@param key [String] @return [Number,nil]

# File lib/ax/application.rb, line 326
def hold_modifier key
  code = EventGenerator::CUSTOM[key]
  raise ArgumentError, "Invalid modifier `#{key}' given" unless code
  KeyCoder.post_event([code, true])
  yield
ensure
  KeyCoder.post_event([code, false]) if code
  code
end
info_plist() click to toggle source

Return the ‘Info.plist` data for the application. This is a plist file that all bundles in OS X must contain.

Many bits of metadata are stored in the plist, check the [reference](developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigFiles.html) for more details.

@return [Hash]

# File lib/ax/application.rb, line 214
def info_plist
  bundle.infoDictionary
end
inspect() click to toggle source

Override the base class to make sure the pid is included.

Calls superclass method AX::Element#inspect
# File lib/ax/application.rb, line 405
def inspect
  super.sub! />$/, "#{pp_checkbox(:focused)} pid=#{pid}>"
end
navigate_menu(*path) click to toggle source

Navigate the menu bar menus for the receiver. This method will not select the last item, but it will open each menu along the path.

You may also be interested in {#select_menu_item}.

@param path [String,Regexp] @return [AX::MenuItem]

perform(name) click to toggle source

@see AX::Element#perform

Calls superclass method AX::Element#perform
# File lib/ax/application.rb, line 276
def perform name
  case name
  when :terminate
    return true if terminated?
    @app.terminate; spin 0.25; terminated?
  when :force_terminate
    return true if terminated?
    @app.forceTerminate; spin 0.25; terminated?
  when :hide
    return true if hidden?
    @app.hide; spin 0.25; hidden?
  when :unhide
    return true if active?
    @app.activateWithOptions(NSRunningApplication::NSApplicationActivateIgnoringOtherApps)
    spin 0.25; active?
  else
    super
  end
end
select_menu_item(*path) click to toggle source

Navigate the menu bar menus for the receiver and select the menu item at the end of the given path. This method will open each menu in the path.

@example

safari.select_menu_item 'Edit', 'Find', /Google/

@param path [String,Regexp] @return [AX::MenuItem]

# File lib/ax/application.rb, line 347
def select_menu_item *path
  target = navigate_menu(*path)
  target.perform :press
  target
end
set(attr, value) click to toggle source

(see AX::Element#set)

Calls superclass method AX::Element#set
# File lib/ax/application.rb, line 181
def set attr, value
  case attr
  when :focused
    perform(value ? :unhide : :hide)
  when :active, :hidden
    perform(value ? :hide : :unhide)
  else
    super
  end
end
show_about_window() click to toggle source

Show the “About” window for the app. Returns the window that is opened.

@return [AX::Window]

# File lib/ax/application.rb, line 380
def show_about_window
  windows = self.children.select { |x| x.kind_of? AX::Window }
  select_menu_item self.title, /^About /
  wait_for(:window, parent: self) { |window| !windows.include?(window) }
end
show_preferences_window() click to toggle source

@note This method assumes that the app has setup the standard

CMD+, hotkey to open the pref window

Try to open the preferences for the app. Returns the window that is opened.

@return [AX::Window]

# File lib/ax/application.rb, line 394
def show_preferences_window
  windows = self.children.select { |x| x.kind_of? AX::Window }
  type "\\COMMAND+,"
  wait_for(:window, parent: self) { |window| !windows.include?(window) }
end
terminate() click to toggle source

@note This is often async and may return before the action is completed

Ask the app to quit

@return [Boolean]

# File lib/ax/application.rb, line 241
def terminate
  perform :terminate
end
terminate!() click to toggle source

@note This is often async and may return before the action is completed

Force the app to quit

@return [Boolean]

# File lib/ax/application.rb, line 251
def terminate!
  perform :force_terminate
end
terminated?() click to toggle source

Ask the app whether or not it is still running.

# File lib/ax/application.rb, line 175
def terminated?
  spin
  @app.terminated?
end
type(string) click to toggle source

Send keyboard input to the focused control element; this is not necessarily an element belonging to the receiving app.

For details on how to format the string, check out the [Keyboarding documentation](github.com/Marketcircle/AXElements/wiki/Keyboarding).

@param string [String] @return [Boolean]

# File lib/ax/application.rb, line 305
def type string
  perform(:unhide) unless focused?
  keyboard_events_for(string).each do |event|
    KeyCoder.post_event event
  end
end
Also aliased as: type_string
type_string(string)
Alias for: type
unhide() click to toggle source

@note This is often async and may return before the action is completed

As the app to unhide itself and bring to front

@return [Boolean]

# File lib/ax/application.rb, line 271
def unhide
  perform :unhide
end
version() click to toggle source

Get the version string for the application.

@example

AX::Application.new("Safari").version    # => "5.2"
AX::Application.new("Terminal").version  # => "2.2.2"
AX::Application.new("Daylite").version   # => "3.15 (build 3664)"

@return [String]

# File lib/ax/application.rb, line 228
def version
  bundle.objectForInfoDictionaryKey 'CFBundleShortVersionString'
end
writable?(attr) click to toggle source

(see AX::Element#writable?)

Calls superclass method AX::Element#writable?
# File lib/ax/application.rb, line 148
def writable? attr
  case attr
  when :focused?, :focused, :hidden?, :hidden then true
  else super
  end
end

Private Instance Methods

bundle() click to toggle source

@return [NSBundle]

# File lib/ax/application.rb, line 424
def bundle
  @bundle ||= NSBundle.bundleWithURL @app.bundleURL
end
init_with_bundle_id(id) click to toggle source
# File lib/ax/application.rb, line 428
def init_with_bundle_id id
  app = NSRunningApplication.runningApplicationsWithBundleIdentifier id
  app.first
end
init_with_name(name) click to toggle source
# File lib/ax/application.rb, line 433
def init_with_name name
  spin
  NSWorkspace.sharedWorkspace.runningApplications.find { |app|
    app.localizedName == name
  }
end
try_launch(id) click to toggle source
# File lib/ax/application.rb, line 440
def try_launch id
  10.times do
    app = init_with_bundle_id id
    return app if app
    if AX::Application.launch id
      spin 1
    else
      raise "#{id} is not a registered bundle identifier for the system"
    end
  end
  raise "#{id} failed to launch in time"
end