This documentation is an overview of the JavaScript API provided by Phoenix. Use this as a guide for writing your window management script. Your script should reside in ~/.phoenix.js. Alternatively — if you prefer — you may also have your script in ~/Library/Application Support/Phoenix/phoenix.js or ~/.config/phoenix/phoenix.js. Phoenix includes Underscore.js (1.8.3) — you can use its features in your configuration. Underscore provides useful helpers for handling JavaScript functions and objects. You may also use JavaScript preprocessing and languages such as CoffeeScript to write your Phoenix-configuration.
- Keys
- Events
- Require
- Phoenix
- Point
- Size
- Rectangle
- Identifiable
- KeyHandler
- EventHandler
- Modal
- Command
- Screen
- Mouse
- App
- Window
This documentation uses pseudocode to outline the API. Many of the classes represent global objects in the script’s context — functions that are marked as static can be accessed through these global objects. All other functions are instance functions. Instance objects can be accessed through the global objects.
For example, to bind a key to a function, you call the bind-function for the Phoenix-object. Notice that you must keep a reference to the handler, otherwise your callback will not get called.
var handler = Phoenix.bind('q', [ 'ctrl', 'shift' ], function () {});To move the focused window to a new coordinate, you can call the setTopLeft-function for a Window-instance. To get a Window-instance, you can for example get the focused window with the focusedWindow-function for the global Window-object.
Window.focusedWindow().setTopLeft({ x: 0, y: 0 });To combine, bind a key to move the focused window.
var handler = Phoenix.bind('q', [ 'ctrl', 'shift' ], function () {
Window.focusedWindow().setTopLeft({ x: 0, y: 0 });
});As an other example, to bind an event to a function, you call the on-function for the Phoenix-object. Again notice that you must keep a reference to the handler, otherwise your callback will not get called.
var handler = Phoenix.on('screensDidChange', function () {});Your configuration file is loaded when the app launches. All functions are evaluated (and executed if necessary) when this happens. Phoenix also reloads the configuration when any changes are detected to the file. You may also reload the configuration manually from the status bar or programmatically from your script.
The following locations are valid configuration paths and the first existing file will be used. You may also use these paths for the debug-configuration (-debug.js). Whilst loading, all symlinks will be resolved, so in the end your configuration can also be a symlink to any desired destination.
~/.phoenix.js~/Library/Application Support/Phoenix/phoenix.js~/.config/phoenix/phoenix.js
You may add JavaScript preprocessing to your configuration by adding a Shebang-directive to the beginning of your file. It must be the first statement in your file. Phoenix should support all popular JavaScript compilers, but be aware that you need to have the compiler installed on your setup and accessible through your shell’s PATH for Phoenix to find it. You also need to ask the compiler to output to the standard output so Phoenix is able to evaluate the result. For example, use CoffeeScript to write your configuration:
#!/usr/bin/env coffee -p
keys = []
keys.push Phoenix.bind 's', [ 'ctrl', 'shift' ], ->
App.launch('Safari').focus()Or use Babel to use ECMAScript 6 JavaScript:
#!/usr/bin/env babel
const keys = [];
keys.push(Phoenix.bind('s', [ 'ctrl', 'shift' ], () => {
App.launch('Safari').focus();
}));All valid keys for binding are as follows:
- Modifiers:
cmd,alt,ctrlandshift(case insensitive) - Keys: case insensitive character or case sensitive special key including function keys, arrow keys, keypad keys etc. as listed below
- You can bind any key on your local keyboard layout, for instance an
å-character if your keyboard has one
- Action:
return,tab,space,delete,escape,help,home,pageUp,forwardDelete,end,pageDown,left,right,downandup - Function:
f1–f19 - Keypad:
keypad.,keypad*,keypad+,keypadClear,keypad/,keypadEnter,keypad-,keypad=,keypad0,keypad1,keypad2,keypad3,keypad4,keypad5,keypad6,keypad7,keypad8andkeypad9
Phoenix supports the following (case sensitive) events:
starttriggered once when Phoenix has started and the context is ready, the callback function receives no arguments
screensDidChangetriggered when screens (i.e. displays) are added, removed, or dynamically reconfigured, the callback function receives no arguments
All of the following app events receive the corresponding App-instance as the only argument for the callback function.
appDidLaunchtriggered when an app has launchedappDidTerminatetriggered when an app has terminatedappDidActivatetriggered when an app has activatedappDidHidetriggered when an app becomes hiddenappDidShowtriggered when an app is shown (becomes unhidden)
All of the following window events receive the corresponding Window-instance as the only argument for the callback function.
windowDidOpentriggered when a window has openedwindowDidClosetriggered when a window has closedwindowDidFocustriggered when a window was focused within an appwindowDidMovetriggered when a window has movedwindowDidResizetriggered when a window has resizedwindowDidMinimizetriggered when a window has minimisedwindowDidUnminimizetriggered when a window has unminimised
You can modularise your configuration using the require-function. It will load the referenced JavaScript-file and reload it if any changes are detected. If the path is relative, it is resolved relatively to the absolute location of the .phoenix.js-file. If this file is a symlink, it will be resolved before resolving the location of the required file.
require('path/to/file.js');Use the Phoenix-object for API-level tasks.
class Phoenix
static void reload()
static KeyHandler bind(String key, Array<String> modifiers, Function callback)
static EventHandler on(String event, Function callback)
static void log(String message)
static void notify(String message)
endreload()manually reloads the context and any changes in the configuration filesbind(String key, Array<String> modifiers, Function callback)binds the key character with the specified modifiers (can be an empty list) to a callback function and returns the handler (undefinedif not supported), you must keep a reference to the handler in order for your callback to get called, the callback function receives no arguments, binding overrides any previous handlers for the same key combinationon(String event, Function callback)binds an event to a callback function and returns the handler (undefinedif not supported), you must keep a reference to the handler in order for your callback to get called, you can have multiple handlers for a single eventlog(String message)logs the message to the Consolenotify(String message)delivers the message to the Notification Center
A simple point object for 2D-coordinates.
class Point
property double x
property double y
endA simple 2D-size object.
class Size
property double width
property double height
endA 2D-rectangle representation of a Point and Size.
class Rectangle
property double x
property double y
property double width
property double height
endObjects that implement Identifiable can be identified and compared.
interface Identifiable
int hash()
boolean isEqual(AnyObject object)
endhash()returns the hash value for the objectisEqual(AnyObject object)returnstrueif the object is equal to this object
Use the KeyHandler-object to enable or disable keys. To change a previous handler, bind the key again. A key is disabled automatically when you release your reference to the handler. KeyHandlers are always reset on context reload. Enabling a key combination that has been exclusively registered by another app will fail.
class KeyHandler implements Identifiable
property String key
property Array<String> modifiers
boolean isEnabled()
boolean enable()
boolean disable()
endkeyread-only property for the key character in lower case or case sensitive special keymodifiersread-only property for the key modifiers in lower caseisEnabled()returnstrueif the key handler is enabled, by defaulttrueenable()enables the key handler, returnstrueif successfuldisable()disables the key handler, returnstrueif successful
Use the EventHandler-object to access event properties. You can have multiple handlers for a single event. To disable an event, release your reference to the handler. EventHandlers are always reset on context reload.
class EventHandler implements Identifiable
property String name
endnameread-only property for the event name
Use the Modal-object to display messages as modal windows.
class Modal implements Identifiable
property Point origin
property double duration
property String message
constructor Modal Modal()
Rectangle frame()
void show()
void close()
endoriginproperty for the origin for the modal, the enclosed properties are read-only so you must pass an object for this property, by default(0, 0)durationproperty for the duration (in seconds) for the modal, if the duration is set to0the modal will remain open until closed, by default0messageproperty for the message for the modal, required for the modal to be displayednew Modal()initialises and returns a new modalframe()returns the frame for the modal, the frame is adjusted for the current message, therefor you must first set the message to get an accurate frameshow()shows the modalclose()closes the modal
Use the Command-object to run UNIX-commands.
class Command
static boolean run(String path, Array arguments)
endrun(String path, Array arguments)executes a UNIX-command in a absolute path with the passed arguments and waits until completion, returnstrueif the execution was successful
Use the Screen-object to access frame sizes and other screens on a multi-screen setup. Get the current screen for a window through the Window-object. Beware that a screen can get stale if you keep a reference to it and it is for instance disconnected while you do so.
class Screen implements Identifiable
static Screen mainScreen()
static Array<Screen> screens()
Rectangle frameInRectangle()
Rectangle visibleFrameInRectangle()
Screen next()
Screen previous()
Array<Window> windows()
Array<Window> visibleWindows()
endmainScreen()returns the screen containing the window with the keyboard focusscreens()returns all screens, the first screen in this array corresponds to the primary screen for the systemframeInRectangle()returns the whole frame for the screenvisibleFrameInRectangle()returns the visible frame for the screen subtracting the Dock and Menu from the frame when visiblenext()returns the next screen or the first screen when on the last oneprevious()returns the previous screen or the last screen when on the first onewindows()returns all windows for the screenvisibleWindows()returns all visible windows for the screen
Use the Mouse-object to control the cursor.
class Mouse
static Point location()
static boolean moveTo(Point point)
endlocation()returns the cursor positionmoveTo(Point point)moves the cursor to a given position, returnstrueif successful
Use the App-object to control apps. Beware that an app can get stale if you keep a reference to it and it is for instance terminated while you do so, see isTerminated().
class App implements Identifiable
static App get(String appName)
static App launch(String appName)
static App focusedApp()
static Array<App> runningApps()
int processIdentifier()
String bundleIdentifier()
String name()
boolean isActive()
boolean isHidden()
boolean isTerminated()
Window mainWindow()
Array<Window> windows()
Array<Window> visibleWindows()
boolean activate()
boolean focus()
boolean show()
boolean hide()
boolean terminate()
boolean forceTerminate()
endget(String appName)returns the running app with the given name, returnsundefinedif the app is not currently runninglaunch(String appName)launches to the background and returns the app with the given name, returnsundefinedif unsuccessfulfocusedApp()returns the focused apprunningApps()returns all running appsprocessIdentifier()returns the process identifier (PID) for the app, returns-1if the app does not have a PIDbundleIdentifier()returns the bundle identifier for the appname()returns the name for the appisActive()returnstrueif the app is currently frontmostisHidden()returnstrueif the app is hiddenisTerminated()returnstrueif the app has been terminatedmainWindow()returns the main window for the appwindows()returns all windows for the appvisibleWindows()returns all visible windows for the appactivate()activates the app and brings its windows forward, returnstrueif successfulfocus()activates the app and brings its windows to focus, returnstrueif successfulshow()shows the app, returnstrueif successfulhide()hides the app, returnstrueif successfulterminate()terminates the app, returnstrueif successfulforceTerminate()force terminates the app, returnstrueif successful
Use the Window-object to control windows. Every screen (i.e. display) combines to form a large rectangle. Every window lives within this rectangle and their position can be altered by giving coordinates inside this rectangle. To position a window to a specific display, you need to calculate its position within the large rectangle. To figure out the coordinates for a given screen, use the functions in Screen. Beware that a window can get stale if you keep a reference to it and it is for instance closed while you do so.
class Window implements Identifiable
static Window focusedWindow()
static Array<Window> windows()
static Array<Window> visibleWindows()
static Array<Window> visibleWindowsInOrder()
Array<Window> otherWindowsOnSameScreen()
Array<Window> otherWindowsOnAllScreens()
String title()
boolean isMain()
boolean isNormal()
boolean isMinimized()
boolean isVisible()
App app()
Screen screen()
Point topLeft()
Size size()
Rectangle frame()
boolean setTopLeft(Point point)
boolean setSize(Size size)
boolean setFrame(Rectangle frame)
boolean maximize()
boolean minimize()
boolean unminimize()
Array<Window> windowsToWest()
Array<Window> windowsToEast()
Array<Window> windowsToNorth()
Array<Window> windowsToSouth()
boolean focus()
boolean focusClosestWindowInWest()
boolean focusClosestWindowInEast()
boolean focusClosestWindowInNorth()
boolean focusClosestWindowInSouth()
endfocusedWindow()returns the focused window for the currently active app, can beundefinedif no window is focused currentlywindows()returns all windows in screensvisibleWindows()returns all visible windows in screensvisibleWindowsInOrder()returns all visible windows in the order as they appear on the screen (from front to back), essentially returning them in the most-recently-used orderotherWindowsOnSameScreen()returns all other windows on the same screen as the windowotherWindowsOnAllScreens()returns all other windows on all screenstitle()returns the title for the windowisMain()returnstrueif the window is the main window for its appisNormal()returnstrueif the window is a normal windowisMinimized()returnstrueif the window is minimisedisVisible()returnstrueif the window is a normal and unminimised window that belongs to an unhidden appapp()returns the app for the windowscreen()returns the screen where most or all of the window is currently presenttopLeft()returns the top left point for the windowsize()returns the size for the windowframe()returns the frame for the windowsetTopLeft(Point point)sets the top left point for the window, returnstrueif successfulsetSize(Size size)sets the size for the window, returnstrueif successfulsetFrame(Rectangle frame)sets the frame for the window, returnstrueif successfulmaximize()resizes the window to fit the whole visible frame for the screen, returnstrueif successfulminimize()minimises the window, returnstrueif successfulunminimize()unminimises the window, returnstrueif successfulwindowsToWest()returns windows to the west of the windowwindowsToEast()returns windows to the east of the windowwindowsToNorth()returns windows to the north the windowwindowsToSouth()returns windows to the south the windowfocus()focuses the window, returnstrueif successfulfocusClosestWindowInWest()focuses the closest window to the west of the window, returnstrueif successfulfocusClosestWindowInEast()focuses the closest window to the east of the window, returnstrueif successfulfocusClosestWindowInNorth()focuses the closest window to the north of the window, returnstrueif successfulfocusClosestWindowInSouth()focuses the closest window to the south of the window, returnstrueif successful