{"connections":[{"sourceLocalID":3,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":1,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":4,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":9,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":11,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":8,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":2,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":6,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"},{"sourceLocalID":7,"sourcePortID":"outlet_output","targetLocalID":0,"targetPortID":"inlet_input"}],"name":"Window Manager Shortcuts","nodes":[{"config":{"script":"# Runs with tools every Mac has: /bin/bash hands the script below to\n# /usr/bin/osascript as JavaScript. No Python, no developer tools.\n# PAYLOAD_action is \"position\" (with fractions PAYLOAD_x, _y, _w, _h of the\n# screen) or \"next_display\". Both come from the trigger's Custom Arguments.\n/usr/bin/osascript -l JavaScript <<'JS'\nObjC.import('AppKit');\n\nfunction run() {\n  var env = $.NSProcessInfo.processInfo.environment;\n  function getenv(name) {\n    var v = ObjC.unwrap(env.objectForKey(name));\n    return typeof v === 'string' ? v : undefined;\n  }\n  // A fraction of the screen, such as 0.5. Missing means 0; anything that is\n  // not a number stops the run with a message instead of guessing.\n  function fraction(name) {\n    var raw = getenv('PAYLOAD_' + name);\n    if (raw === undefined) { raw = '0'; }\n    if (!/^\\s*[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?\\s*$/.test(raw)) {\n      throw new Error('Custom Argument ' + name + ' must be a number such as 0.5, got \"' + raw + '\"');\n    }\n    return Number(raw);\n  }\n\n  var action = getenv('PAYLOAD_action') || '';\n  if (action !== 'position' && action !== 'next_display') {\n    throw new Error('Custom Argument action must be position or next_display, got \"' + action + '\". Press one of the shortcuts rather than Run.');\n  }\n\n  // Every display, in the top-left coordinates System Events uses. `full` is\n  // the whole display (used to find which one the window is on); `usable` is\n  // the area left after the menu bar and the Dock (where windows are placed).\n  var screens = $.NSScreen.screens.js;\n  if (screens.length === 0) { throw new Error('No displays found'); }\n  var mainHeight = screens[0].frame.size.height;\n  function topLeft(r) {\n    return { x: r.origin.x, y: mainHeight - (r.origin.y + r.size.height), w: r.size.width, h: r.size.height };\n  }\n  var displays = [];\n  for (var i = 0; i < screens.length; i++) {\n    displays.push({ full: topLeft(screens[i].frame), usable: topLeft(screens[i].visibleFrame) });\n  }\n  // Left to right, then top to bottom.\n  displays.sort(function (a, b) { return (a.full.x - b.full.x) || (a.full.y - b.full.y); });\n\n  // The frontmost window of the app you are using.\n  var procs = Application('System Events').applicationProcesses.whose({ frontmost: true });\n  if (procs.length === 0) { throw new Error('No frontmost app'); }\n  var win = procs[0].windows[0];\n  var pos = win.position();\n  var size = win.size();\n  var wx = Math.trunc(pos[0]), wy = Math.trunc(pos[1]);\n  var ww = Math.trunc(size[0]), wh = Math.trunc(size[1]);\n\n  // The display holding the window's centre (the first one if none does).\n  var cx = wx + Math.floor(ww / 2), cy = wy + Math.floor(wh / 2);\n  var current = 0;\n  for (var d = 0; d < displays.length; d++) {\n    var f = displays[d].full;\n    if (f.x <= cx && cx < f.x + f.w && f.y <= cy && cy < f.y + f.h) { current = d; break; }\n  }\n\n  var nx, ny, nw, nh;\n  if (action === 'next_display') {\n    // Move to the next display, wrapping after the last one, keeping the\n    // window's place and size relative to the screen.\n    var curr = displays[current].usable;\n    var next = displays[(current + 1) % displays.length].usable;\n    var rx = (wx - curr.x) / curr.w, ry = (wy - curr.y) / curr.h;\n    var rw = ww / curr.w, rh = wh / curr.h;\n    nx = Math.trunc(next.x + rx * next.w);\n    ny = Math.trunc(next.y + ry * next.h);\n    nw = Math.trunc(rw * next.w);\n    nh = Math.trunc(rh * next.h);\n  } else {\n    // Tile on the current display.\n    var area = displays[current].usable;\n    var x = fraction('x'), y = fraction('y'), w = fraction('w'), h = fraction('h');\n    nx = Math.trunc(area.x + x * area.w);\n    ny = Math.trunc(area.y + y * area.h);\n    nw = Math.trunc(w * area.w);\n    nh = Math.trunc(h * area.h);\n  }\n\n  win.position = [nx, ny];\n  win.size = [nw, nh];\n}\nJS\n","shell":"/bin/bash"},"customName":"Tile Window","isDisabled":false,"localID":0,"typeID":"action.script","x":460,"y":260},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.667","x":"0.333","y":"0"},"shortcut":"ctrl+option+cmd+right"},"customName":"Right 2/3","isDisabled":false,"localID":1,"typeID":"trigger.keyboard_shortcut","x":-280,"y":160},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.5","x":"0","y":"0"},"shortcut":"ctrl+option+shift+cmd+left"},"customName":"Left Half","isDisabled":false,"localID":2,"typeID":"trigger.keyboard_shortcut","x":-260,"y":720},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.333","x":"0","y":"0"},"shortcut":"option+cmd+left"},"customName":"Left 1/3","isDisabled":false,"localID":3,"typeID":"trigger.keyboard_shortcut","x":-160,"y":-220},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.333","x":"0.667","y":"0"},"shortcut":"option+cmd+right"},"customName":"Right 1/3","isDisabled":false,"localID":4,"typeID":"trigger.keyboard_shortcut","x":-160,"y":-100},{"config":{"_height":620,"_width":460,"text":"**Window Manager Shortcuts snaps the window you are working in into place with a keyboard shortcut.**\n\n**What it does**\n- Nine shortcuts all feed **Tile Window**, which moves and resizes the frontmost window of the app you are using.\n- Option Command Left or Right: left or right third.\n- Control Option Command Left or Right: left or right two thirds.\n- Control Option Shift Command Left or Right: left or right half.\n- Control Option Shift Command F: fill the screen.\n- Control Option Shift Command Up or Down: move the window to your next display.\n- Windows fit the space left by the menu bar and the Dock, on whichever display the window is on.\n\n**Set it up**\n- Grant Watchflows **Accessibility** in System Settings, Privacy & Security, Accessibility. The shortcuts and the window moves both need it. If macOS asks to let Watchflows control System Events, allow it.\n- Some of these shortcuts may already belong to another app or to macOS. Click any trigger and record your own.\n- Turn the flow on.\n\n**Make it yours**\n- Add a layout: copy a trigger, record a new shortcut and change its Custom Arguments. `action` is `position`. `x` and `y` place the window's top left corner and `w` and `h` set its width and height, each as a fraction of the screen from 0 to 1.\n- For example, a centred window is `x 0.15`, `y 0.1`, `w 0.7`, `h 0.8`, and the top half is `x 0`, `y 0`, `w 1`, `h 0.5`.\n- A trigger whose `action` is `next_display` moves the window to the next display instead, keeping its place and size on the screen."},"isDisabled":false,"localID":5,"typeID":"note","x":-740,"y":-380},{"config":{"consumeKey":true,"customArgs":{"action":"next_display"},"shortcut":"ctrl+option+shift+cmd+down"},"customName":"Next Display","isDisabled":false,"localID":6,"typeID":"trigger.keyboard_shortcut","x":-60,"y":1140},{"config":{"consumeKey":true,"customArgs":{"action":"next_display"},"shortcut":"ctrl+option+shift+cmd+up"},"customName":"Next Display","isDisabled":false,"localID":7,"typeID":"trigger.keyboard_shortcut","x":-120,"y":1000},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.5","x":"0.5","y":"0"},"shortcut":"ctrl+option+shift+cmd+right"},"customName":"Right Half","isDisabled":false,"localID":8,"typeID":"trigger.keyboard_shortcut","x":-260,"y":600},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"1","x":"0","y":"0"},"shortcut":"ctrl+option+shift+cmd+f"},"customName":"Full Screen","isDisabled":false,"localID":9,"typeID":"trigger.keyboard_shortcut","x":-320,"y":380},{"config":{"_height":200,"_width":400,"text":"**Tile Window** reads `action`, `x`, `y`, `w` and `h` from the shortcut that fired. It finds each display's size with the JavaScript built into macOS and moves the window through System Events, so there is nothing to install. Next Display goes left to right through your displays and wraps back to the first."},"isDisabled":false,"localID":10,"typeID":"note","x":400,"y":460},{"config":{"consumeKey":true,"customArgs":{"action":"position","h":"1","w":"0.667","x":"0","y":"0"},"shortcut":"ctrl+option+cmd+left"},"customName":"Left 2/3","isDisabled":false,"localID":11,"typeID":"trigger.keyboard_shortcut","x":-280,"y":40}],"version":1}