kasper / phoenix

A lightweight macOS window and app manager scriptable with JavaScript
https://kasper.github.io/phoenix/
Other
4.39k stars 127 forks source link

How to send window to space n? #202

Closed fiedl closed 6 years ago

fiedl commented 6 years ago

macOS does provide keyboard shortcuts for switching to space n, for example ctrl+3 to switch to space 3.

bildschirmfoto 2018-04-10 um 14 57 32

I'm trying to implement a shortcut with phoenix in order to send the active window (Window.focused()) to the nth space in the above sense.

Is there a way to get an array of spaces in the order that macOS uses for ctrl+n.

mafredri commented 6 years ago

Have you tried Space.all()? According to documentation:

Returns all spaces, the first space in this array corresponds to the primary space (macOS 10.11+, returns an empty list otherwise).

I've never used spaces myself so can't be of much help here (you could also try to figure out if space.hash() always produces the same hash, and map it to N).

kasper commented 6 years ago

If I remember correctly the array should be ordered. Also the hash value for each space is their identifier.

fiedl commented 6 years ago

Thanks! Space.all() did the trick. I just needed to filter for normal spaces and the same screen.

Solution:

# ~/.phoenix.js
#!/usr/bin/env coffee -p

for i in [1..9]
  ((i)-> # needed for scoping. otherwise i will always be n+1 when the callback is called.
    Key.on i, ['ctrl', 'alt'], -> move_active_window_to_space i
  )(i)

spaces_of_current_screen = ->
  _.filter(Space.all(), (space)->
    _.includes(space.screens(), active_window().screen()) && space.isNormal()
  )

space = (i)->
  spaces_of_current_screen()[i - 1]

active_window = ->
  Window.focused()

move_active_window_to_space = (i)->
  Space.active().removeWindows [active_window()]
  space(i).addWindows [active_window()]
kasper commented 6 years ago

@fiedl Nice! There’s also Screen#spaces().

l00sed commented 2 years ago

@fiedl This is the best i3wm alternative setup I could find for Mac OS! I was very frustrated that yabai requires disabling SIP in order to move windows around. Finally, I've discovered a solution to throw windows to numbered spaces. Thanks so much. For anyone who'd rather use regular JS:

const ALT_SHIFT = ["alt", "shift"];
const ALT_CTRL = ["alt", "control"];
let _i;

/**
 * Move to Numbered Space
 *
 * Adapted from fiedl's coffeescript phoenix.js dotfile:
 * https://github.com/fiedl/dotfiles/
 *
 * Add Option/Alt Key + [1-9] to System Preferences > Keyboard > Shortcuts
 * to quickly switch between numbered spaces.
 * Use "WhichSpace" to see active space in menu bar--- looking for better solution.
 *
 */
const _fn = (i) => {
  Key.on(i, ALT_SHIFT, () => {
    return move_active_window_to_space(i);
  });
  return Key.on(i, ALT_CTRL, () => {
    return move_active_window_and_go_to_space(i);
  });
};

const assignment = (() => {
  for (let i=_i=1;_i<=9;i=++_i) {
    _fn(i);
  }
})();

const spaces_of_current_screen = () => {
  return _.filter(Space.all(), function(space) {
    return _.includes(space.screens(), active_window().screen()) && space.isNormal();
  });
};

const space = (i) => {
  return spaces_of_current_screen()[i - 1];
};

const active_window = () => {
  return Window.focused();
};

const move_active_window_to_space = (i) => {
  Space.active().removeWindows([active_window()]);
  return space(i).moveWindows([active_window()]);
};

const move_active_window_and_go_to_space = (i) => {
  move_active_window_to_space(i);
  return active_window().focus();
};

@kasper Could you elaborate on Screen#spaces()?

koekeishiya commented 2 years ago

I was very frustrated that yabai requires disabling SIP in order to move windows around

yabai does not need SIP disabled to move windows around. It needs SIP disabled to modify spaces.

l00sed commented 2 years ago

Hi @koekeishiya, thanks for seeking some clarity. I'm not super familiar with the terminology, and I think I used the term window when I meant space. With yabai running and SIP enabled, it does not have the ability to send windows to space n, AFAIK. I've found that this phoenix configuration is a good solution to use (even in tandem with the SIP-enabled yabai) in order to mimic i3wm-like window movements across numbered spaces.

koekeishiya commented 2 years ago

With yabai running and SIP enabled, it does not have the ability to send windows to space n

You can do this with SIP enabled: yabai -m window --space n. It uses the following API which is not protected in any way SLSMoveWindowsToManagedSpace.

l00sed commented 2 years ago

Well hot Daniel, that works. Thanks for pointing that out @koekeishiya. Still glad that phoenix can be scripted to do this too. Sorry for bloating this issue.

kasper commented 2 years ago

@l00sed Oh, right, I was just referring that you could use Screen#spaces() to replace spaces_of_current_screen.

l00sed commented 2 years ago

Oh, awesome. Thanks for that.