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
- Preferences
- Require
- Phoenix
- Point
- Size
- Rectangle
- Identifiable
- Iterable
- KeyHandler
- EventHandler
- TimerHandler
- Modal
- Command
- Screen
- Space
- 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(s). 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
,ctrl
andshift
(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
,down
andup
- Function:
f1
–f19
- Keypad:
keypad.
,keypad*
,keypad+
,keypadClear
,keypad/
,keypadEnter
,keypad-
,keypad=
,keypad0
,keypad1
,keypad2
,keypad3
,keypad4
,keypad5
,keypad6
,keypad7
,keypad8
andkeypad9
Phoenix supports the following (case sensitive) events:
start
triggered once when Phoenix has started and the context is ready
screensDidChange
triggered when screens (i.e. displays) are added, removed, or dynamically reconfigured
spaceDidChange
, triggered when the active space has changed
All of the following app events receive the corresponding App
-instance as the first argument for the callback function.
appDidLaunch
triggered when an app has launchedappDidTerminate
triggered when an app has terminatedappDidActivate
triggered when an app has activatedappDidHide
triggered when an app becomes hiddenappDidShow
triggered when an app is shown (becomes unhidden)
All of the following window events receive the corresponding Window
-instance as the first argument for the callback function.
windowDidOpen
triggered when a window has openedwindowDidClose
triggered when a window has closedwindowDidFocus
triggered when a window was focused within an appwindowDidMove
triggered when a window has movedwindowDidResize
triggered when a window has resizedwindowDidMinimize
triggered when a window has minimisedwindowDidUnminimize
triggered when a window has unminimised
Phoenix supports the following (case sensitive) preferences:
daemon
(boolean): if settrue
Phoenix will run completely in the background, this also removes the status bar menu, defaults tofalse
openAtLogin
(boolean): if settrue
Phoenix will automatically open at login, defaults tofalse
Set the preferences using the Phoenix
-object — for example:
Phoenix.set({
'daemon': true,
'openAtLogin': true
});
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 TimerHandler after(double interval, Function callback)
static TimerHandler every(double interval, Function callback)
static void set(Map<String, AnyObject> preferences)
static void log(String message)
static void notify(String message)
end
reload()
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 (undefined
if not supported), you must keep a reference to the handler in order for your callback to get called, the callback function receives its handler as the only argument, 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 (undefined
if 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 event, the callback function receives its handler as the last argument, for any additional arguments see eventsafter(double interval, Function callback)
creates a timer that fires the callback once after the given interval (in seconds) and returns the handler, you must keep a reference to the handler in order for your callback to get called, the callback function receives its handler as the only argumentevery(double interval, Function callback)
creates a timer that fires the callback repeatedly until stopped using the given interval (in seconds) and returns the handler, you must keep a reference to the handler in order for your callback to get called, the callback function receives its handler as the only argumentset(Map<String, AnyObject> preferences)
sets the preferences from the given key–value map, any previously set preferences with the same key will be overriddenlog(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
end
A simple 2D-size object.
class Size
property double width
property double height
end
A 2D-rectangle representation of a Point
and Size
.
class Rectangle
property double x
property double y
property double width
property double height
end
Objects that implement Identifiable
can be identified and compared.
interface Identifiable
int hash()
boolean isEqual(AnyObject object)
end
Objects that implement Iterable
can be traversed.
interface Iterable
Object next()
Object previous()
end
next()
returns the next object or the first object when on the last oneprevious()
returns the previous object or the last object when on the first one
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()
end
key
read-only property for the key character in lower case or case sensitive special keymodifiers
read-only property for the key modifiers in lower caseisEnabled()
returnstrue
if the key handler is enabled, by defaulttrue
enable()
enables the key handler, returnstrue
if successfuldisable()
disables the key handler, returnstrue
if 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
end
name
read-only property for the event name
Use the TimerHandler
-object to control timers. A timer can fire only once or be repeating. To release a timer, release your reference to the handler. TimerHandlers are always reset on context reload.
class TimerHandler implements Identifiable
void stop()
end
stop()
stops the timer immediately
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()
end
origin
property 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)
duration
property for the duration (in seconds) for the modal, if the duration is set to0
the modal will remain open until closed, by default0
message
property 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)
end
run(String path, Array arguments)
executes a UNIX-command in a absolute path with the passed arguments and waits until completion, returnstrue
if 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, Iterable
static Screen mainScreen()
static Array<Screen> screens()
String identifier()
Rectangle frameInRectangle()
Rectangle visibleFrameInRectangle()
Array<Space> spaces() // OS X 10.11+
Array<Window> windows()
Array<Window> visibleWindows()
end
mainScreen()
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 systemidentifier()
returns the UUID for the screenframeInRectangle()
returns the whole frame for the screenvisibleFrameInRectangle()
returns the visible frame for the screen subtracting the Dock and Menu from the frame when visiblespaces()
returns all spaces for the screen (OS X 10.11+, returns an empty list otherwise)windows()
returns all windows for the screenvisibleWindows()
returns all visible windows for the screen
Use the Space
-object to control spaces. These features are only supported on El Capitan (10.11) and upwards. A single window can be in multiple spaces at the same time. To move a window to a different space, remove it from any existing spaces and add it to a new one. You can switch to a space by focusing on a window in that space. Beware that a space can get stale if you keep a reference to it and it is for instance closed while you do so.
class Space implements Identifiable, Iterable
static Space activeSpace() // OS X 10.11+
static Array<Space> spaces() // OS X 10.11+
boolean isNormal()
boolean isFullScreen()
Screen screen()
Array<Window> windows()
Array<Window> visibleWindows()
void addWindows(Array<Window> windows)
void removeWindows(Array<Window> windows)
end
activeSpace()
returns the space containing the window with the keyboard focus (OS X 10.11+, returnsundefined
otherwise)spaces()
returns all spaces, the first space in this array corresponds to the primary space (OS X 10.11+, returns an empty list otherwise)isNormal()
returnstrue
if the space is a normal spaceisFullScreen()
returnstrue
if the space is a full screen spacescreen()
returns the screen to which the space belongs towindows()
returns all windows for the spacevisibleWindows()
returns all visible windows for the spaceaddWindows(Array<Window> windows)
adds the given windows to the spaceremoveWindows(Array<Window> windows)
removes the given windows from the space
Use the Mouse
-object to control the cursor.
class Mouse
static Point location()
static boolean moveTo(Point point)
end
location()
returns the cursor positionmoveTo(Point point)
moves the cursor to a given position, returnstrue
if 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()
end
get(String appName)
returns the running app with the given name, returnsundefined
if the app is not currently runninglaunch(String appName)
launches to the background and returns the app with the given name, returnsundefined
if unsuccessfulfocusedApp()
returns the focused apprunningApps()
returns all running appsprocessIdentifier()
returns the process identifier (PID) for the app, returns-1
if the app does not have a PIDbundleIdentifier()
returns the bundle identifier for the appname()
returns the name for the appisActive()
returnstrue
if the app is currently frontmostisHidden()
returnstrue
if the app is hiddenisTerminated()
returnstrue
if 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, returnstrue
if successfulfocus()
activates the app and brings its windows to focus, returnstrue
if successfulshow()
shows the app, returnstrue
if successfulhide()
hides the app, returnstrue
if successfulterminate()
terminates the app, returnstrue
if successfulforceTerminate()
force terminates the app, returnstrue
if 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 isFullScreen()
boolean isMinimized()
boolean isVisible()
App app()
Screen screen()
Array<Space> spaces() // OS X 10.11+
Point topLeft()
Size size()
Rectangle frame()
boolean setTopLeft(Point point)
boolean setSize(Size size)
boolean setFrame(Rectangle frame)
boolean setFullScreen(boolean value)
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()
end
focusedWindow()
returns the focused window for the currently active app, can beundefined
if 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()
returnstrue
if the window is the main window for its appisNormal()
returnstrue
if the window is a normal windowisFullScreen()
returnstrue
if the window is a full screen windowisMinimized()
returnstrue
if the window is minimisedisVisible()
returnstrue
if 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 presentspaces()
returns the spaces where the window is currently present (OS X 10.11+, returns an empty list otherwise)topLeft()
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, returnstrue
if successfulsetSize(Size size)
sets the size for the window, returnstrue
if successfulsetFrame(Rectangle frame)
sets the frame for the window, returnstrue
if successfulsetFullScreen(boolean value)
sets whether the window is full screen, returnstrue
if successfulmaximize()
resizes the window to fit the whole visible frame for the screen, returnstrue
if successfulminimize()
minimises the window, returnstrue
if successfulunminimize()
unminimises the window, returnstrue
if 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, returnstrue
if successfulfocusClosestWindowInWest()
focuses the closest window to the west of the window, returnstrue
if successfulfocusClosestWindowInEast()
focuses the closest window to the east of the window, returnstrue
if successfulfocusClosestWindowInNorth()
focuses the closest window to the north of the window, returnstrue
if successfulfocusClosestWindowInSouth()
focuses the closest window to the south of the window, returnstrue
if successful