Class: AX::Application
- Includes:
- Accessibility::Keyboard
- Defined in:
- lib/ax/application.rb
Overview
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.
Attributes collapse
-
#active? ⇒ Boolean
(also: #focused, #focused?)
Ask the app whether or not it is the active app.
-
#attribute(attr) ⇒ Object
Get the value of an attribute.
-
#bundle_identifier ⇒ String
Get the bundle identifier for the application.
-
#hidden? ⇒ Boolean
Ask the app whether or not it is hidden.
-
#info_plist ⇒ Hash
Return the
Info.plist
data for the application. -
#set(attr, value) ⇒ Object
Set a writable attribute on the element to the given value.
-
#terminated? ⇒ Boolean
Ask the app whether or not it is still running.
-
#version ⇒ String
Get the version string for the application.
-
#writable?(attr) ⇒ Object
Check whether or not an attribute is writable.
Actions collapse
-
#hide ⇒ Boolean
Ask the app to hide itself.
-
#hold_modifier(key) ⇒ Number?
Press the given modifier key and hold it down while yielding to the given block.
-
#navigate_menu(*path) ⇒ AX::MenuItem
Navigate the menu bar menus for the receiver.
-
#perform(name) ⇒ Boolean
Tell an object to trigger an action.
-
#select_menu_item(*path) ⇒ AX::MenuItem
Navigate the menu bar menus for the receiver and select the menu item at the end of the given path.
-
#show_about_window ⇒ AX::Window
Show the "About" window for the app.
-
#show_preferences_window ⇒ AX::Window
Try to open the preferences for the app.
-
#terminate ⇒ Boolean
Ask the app to quit.
-
#terminate! ⇒ Boolean
Force the app to quit.
-
#type(string) ⇒ Boolean
(also: #type_string)
Send keyboard input to the receiver, the control in the app that currently has focus will receive the key presses.
-
#unhide ⇒ Boolean
As the app to unhide itself and bring to front.
Class Method Summary collapse
-
.dock ⇒ AX::Application
Find and return the dock application.
-
.finder ⇒ AX::Application
Find and return the dock application.
-
.frontmost_application ⇒ AX::Application
(also: frontmost_app)
Find and return the application which is frontmost.
-
.launch(bundle) ⇒ Boolean
Asynchronously launch an application with given the bundle identifier.
-
.menu_bar_owner ⇒ AX::Application
Find and return the application which owns the menu bar.
-
.notification_center ⇒ AX::Application
Find and return the notification center UI app.
Instance Method Summary collapse
-
#element_at(point) ⇒ AX::Element?
Find the element in the receiver that is at point given.
-
#initialize(arg) ⇒ Application
constructor
Standard way of creating a new application object.
-
#inspect ⇒ Object
Override the base class to make sure the pid is included.
Methods inherited from Element
#==, #actions, #ancestor, #ancestry, #application, #attributes, #blank?, #bounds, #children, #description, #inspect_subtree, #invalid?, #method_missing, #methods, #parameterized_attribute, #parameterized_attributes, #pid, #respond_to?, #search, #size_of, #to_h, #to_point, #to_s
Methods included from Accessibility::PrettyPrinter
#pp_checkbox, #pp_children, #pp_enabled, #pp_focused, #pp_identifier, #pp_position
Constructor Details
#initialize(arg) ⇒ Application
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.
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# 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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class AX::Element
Class Method Details
.dock ⇒ AX::Application
Find and return the dock application
31 32 33 |
# File 'lib/ax/application.rb', line 31 def dock new 'com.apple.dock' end |
.finder ⇒ AX::Application
Find and return the dock application
39 40 41 |
# File 'lib/ax/application.rb', line 39 def finder new 'com.apple.finder' end |
.frontmost_application ⇒ AX::Application Also known as: frontmost_app
Find and return the application which is frontmost
This is often, but not necessarily, the same as the app that owns the menu bar.
60 61 62 |
# File 'lib/ax/application.rb', line 60 def frontmost_application new NSWorkspace.sharedWorkspace.frontmostApplication end |
.launch(bundle) ⇒ Boolean
Asynchronously launch an application with given the bundle identifier
20 21 22 23 24 25 |
# 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 ⇒ AX::Application
Find and return the application which owns the menu bar
This is often, but not necessarily, the same as the app that is frontmost.
72 73 74 |
# File 'lib/ax/application.rb', line 72 def new NSWorkspace.sharedWorkspace. end |
.notification_center ⇒ AX::Application
Find and return the notification center UI app
Obviously, this will only work on OS X 10.8+
49 50 51 |
# File 'lib/ax/application.rb', line 49 def notification_center new 'com.apple.notificationcenterui' end |
Instance Method Details
#active? ⇒ Boolean Also known as: focused, focused?
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.
159 160 161 162 |
# File 'lib/ax/application.rb', line 159 def active? spin @app.active? end |
#attribute(attr) ⇒ Object
Get the value of an attribute. This method will return nil
if
the attribute does not have a value or if the element is dead. The
execption to the rule is that the :children
attribute will always
return an array unless the element does not have the :children
attribute.
139 140 141 142 143 144 145 |
# 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 ⇒ String
Get the bundle identifier for the application.
201 202 203 |
# File 'lib/ax/application.rb', line 201 def bundle_identifier @app.bundleIdentifier end |
#element_at(point) ⇒ AX::Element?
Find the element in the receiver that is at point given.
nil
will be returned if there was nothing at that point.
415 416 417 |
# File 'lib/ax/application.rb', line 415 def element_at point @ref.element_at(point).to_ruby end |
#hidden? ⇒ Boolean
Ask the app whether or not it is hidden.
168 169 170 171 |
# File 'lib/ax/application.rb', line 168 def hidden? spin @app.hidden? end |
#hide ⇒ Boolean
This is often async and may return before the action is completed
Ask the app to hide itself
261 262 263 |
# File 'lib/ax/application.rb', line 261 def hide perform :hide end |
#hold_modifier(key) ⇒ Number?
Press the given modifier key and hold it down while yielding to the given block.
325 326 327 328 329 330 331 332 333 |
# File 'lib/ax/application.rb', line 325 def hold_modifier key code = EventGenerator::CUSTOM[key] raise ArgumentError, "Invalid modifier `#{key}' given" unless code @ref.post [[code, true]] yield ensure @ref.post [[code,false]] if code code end |
#info_plist ⇒ Hash
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 for more details.
214 215 216 |
# File 'lib/ax/application.rb', line 214 def info_plist bundle.infoDictionary end |
#inspect ⇒ Object
Override the base class to make sure the pid is included.
404 405 406 |
# File 'lib/ax/application.rb', line 404 def inspect super.sub! />$/, "#{pp_checkbox(:focused)} pid=#{pid}>" end |
#navigate_menu(*path) ⇒ AX::MenuItem
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.
360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/ax/application.rb', line 360 def *path perform :unhide # can't navigate menus unless the app is up front = item = self..(title: path.shift) path.each do |part| item.perform :press next_item = item.(title: part) item = next_item end item ensure # got to the end .perform :cancel unless item.title == path.last end |
#perform(name) ⇒ Boolean
Tell an object to trigger an action.
For instance, you can tell a button to call the same method that would be called when pressing a button, except that the mouse will not move over to the button to press it, nor will the keyboard be used.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# 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) ⇒ AX::MenuItem
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.
346 347 348 349 350 |
# File 'lib/ax/application.rb', line 346 def *path target = *path target.perform :press target end |
#set(attr, value) ⇒ Object
Set a writable attribute on the element to the given value.
181 182 183 184 185 186 187 188 189 190 |
# 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 ⇒ AX::Window
Show the "About" window for the app. Returns the window that is opened.
379 380 381 382 383 |
# File 'lib/ax/application.rb', line 379 def show_about_window windows = self.children.select { |x| x.kind_of? AX::Window } self.title, /^About / wait_for(:window, parent: self) { |window| !windows.include?(window) } end |
#show_preferences_window ⇒ AX::Window
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.
393 394 395 396 397 |
# File 'lib/ax/application.rb', line 393 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 ⇒ Boolean
This is often async and may return before the action is completed
Ask the app to quit
241 242 243 |
# File 'lib/ax/application.rb', line 241 def terminate perform :terminate end |
#terminate! ⇒ Boolean
This is often async and may return before the action is completed
Force the app to quit
251 252 253 |
# File 'lib/ax/application.rb', line 251 def terminate! perform :force_terminate end |
#terminated? ⇒ Boolean
Ask the app whether or not it is still running.
175 176 177 178 |
# File 'lib/ax/application.rb', line 175 def terminated? spin @app.terminated? end |
#type(string) ⇒ Boolean Also known as: type_string
Send keyboard input to the receiver, the control in the app that currently has focus will receive the key presses.
For details on how to format the string, check out the Keyboarding documentation.
305 306 307 308 309 310 |
# 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 |
#unhide ⇒ Boolean
This is often async and may return before the action is completed
As the app to unhide itself and bring to front
271 272 273 |
# File 'lib/ax/application.rb', line 271 def unhide perform :unhide end |
#version ⇒ String
Get the version string for the application.
228 229 230 |
# File 'lib/ax/application.rb', line 228 def version bundle.objectForInfoDictionaryKey 'CFBundleShortVersionString' end |
#writable?(attr) ⇒ Object
Check whether or not an attribute is writable.
148 149 150 151 152 153 |
# File 'lib/ax/application.rb', line 148 def writable? attr case attr when :focused?, :focused, :hidden?, :hidden then true else super end end |