Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a scratchpad like there was in kwm? #379

Closed
hahuang65 opened this issue Jan 22, 2020 · 28 comments
Closed

Is there a scratchpad like there was in kwm? #379

hahuang65 opened this issue Jan 22, 2020 · 28 comments
Labels
suggestion Request for new feature or some form of enhancement

Comments

@hahuang65
Copy link

Trying to have a couple of windows that work as floating scratchpads. Wondering if that's still a thing in yabai?

@koekeishiya
Copy link
Owner

There is currently no such thing in yabai.

@koekeishiya koekeishiya added the question Request for information or help, not an issue label Jan 22, 2020
@hahuang65
Copy link
Author

Wondering if there's been any thought on whether this will be added sometime in the far far future?
Also, great work on yabai. I just moved from kwm yesterday, and this thing is SMOOOOOTH. Thanks for the hard work!

@dominiklohmann
Copy link
Collaborator

dominiklohmann commented Jan 22, 2020

If you minimize a window and save its window id (or label, if assigned one), you can move a minimized window to the current space and deminimize it with one command like this:

yabai -m window <wid> --space $(yabai -m query --spaces --space | jq '.index') &&
    yabai -m window --focus <wid>

One quick idea would be to assign some set of labels to all windows that are supposed to be on a scratch space, and then have one command that minimizes all these windows at once and then another command that brings all windows back with a command similar to the one above. Nevermind this idea, windows cannot be labeled.

@hahuang65
Copy link
Author

@dominiklohmann that's a pretty hot tip. I'm gonna play around with that and see what I can do. Thanks!

@koekeishiya koekeishiya added suggestion Request for new feature or some form of enhancement and removed question Request for information or help, not an issue labels Mar 1, 2020
@sainathadapa
Copy link

@hahuang65 were you able to replicate the scratchpad functionality in yabai?

@hahuang65
Copy link
Author

Nope.

@koekeishiya
Copy link
Owner

So one issue with the scratchpad functionality as it was in kwm, is that upon a crash any window that was on the scratchpad would be lost, as we used private APIs to remove it from all active spaces.

I think it would probably be more suitable to integrate this with the built-in minimize functionality that macOS supports, as mentioned by @dominiklohmann

If adding labels to windows are enough to support that; this can be implemented rather quickly.

@dominiklohmann
Copy link
Collaborator

Labels are essentially just a shortcut for keeping a local cache of window identifiers on disk, they aren't even required to implement this. I don't have a use case for this myself and can't see myself using it, so I'm unlikely to spend further time on it, but I'd be available for help if someone wants to write a ready-to-use script for this.

@koekeishiya
Copy link
Owner

I also do not use this functionality, which makes it hard for me to reason about what a good solution is. I want to try and keep the core of yabai simple and given that I do not use this functionality it makes it hard for me to reason about what a proper solution to this would look like.

I am leaning more towards the goal of giving the user enough power to create a scriptable solution for this, but as I said, I don't actually have much of an idea what would be required that is currently not possible.

@koekeishiya koekeishiya added the help wanted Community help appreciated label Apr 20, 2020
@dominiklohmann
Copy link
Collaborator

dominiklohmann commented Apr 20, 2020

The only thing that's really missing for this is yabai -m window [<selector>] --minimize.

Edit: And a minimized attribute in window queries.

@koekeishiya
Copy link
Owner

So the issue here is that minimized windows are not actually reported by the macOS APIs for most applications (for some reason Chrome does report these windows).

Would it make more sense to add a separate --minimize and --deminimize or to provide a simple --toggle minimize?

@dominiklohmann
Copy link
Collaborator

--focus already deminimizes, and deminimized windows also always gain focus. I don't think an explicit --deminimize is needed.

@koekeishiya
Copy link
Owner

koekeishiya commented Apr 20, 2020 via email

@koekeishiya
Copy link
Owner

Hmm so I actually found a way to always report all minimized windows in the space query. I need to verify that this does not break existing logic, and then we can add minimized to the window attributes.

@koekeishiya
Copy link
Owner

koekeishiya commented Apr 20, 2020

To summarize (changes made to master):

Minimized windows are now included in the result of window queries.
There is a new attribute minimized to identify the current state of a window.

Added command yabai -m window [<selector>] --minimize and a corresponding command to deminimize yabai -m window [<selector>] --deminimize.

As mentioned by @dominiklohmann focusing a window will also deminimize it, and I've mentioned this in the documentation for the deminimize command. I felt that it might be worth having a separate command for it because of the following caveat that I discovered:

I can actually deminimize a window without stealing focus using the AX API, if the application whom the window belongs to is not currently the frontmost application.

However, I might remove the --deminimize command before this enters an actual release based on feedback received or if I decide to try and use this for something myself and find that the additional command to deminimize a window is unnecessary.

This should be enough to make something like a scratchpad at a user level.
If the addition of labels make it easier to identify or manage such windows, I am open to implementing that as well.

@sainathadapa
Copy link

Wow! that was fast! Thanks!

@hahuang65
Copy link
Author

@sainathadapa if you figure out how to script this, could you please post back here? I will do the same, but recent events have made my time to tinker pretty scarce unfortunately.

@sainathadapa
Copy link

Will do 👍 , although i might just make do with a single window in scratchpad at first.

@dominiklohmann
Copy link
Collaborator

This works:

current_space=$(yabai -m query --spaces --space | jq '.index')
yabai -m query --windows |
  jq '.[] | select(.minimized == 1).id' |
  xargs -L1 -I{} sh -c ' {
    yabai -m window $1 --space $2
    yabai -m window $1 --deminimize
    } & ' sh {} $current_space

It deminimizes all currently minimized windows on the current space. So you can add a window by minimizing it, and remove everything from the "scratchpad" by running the above command.

@hahuang65
Copy link
Author

So if I want to have 2 differently named scratchpads, and hotkeys to bring either one into or out of focus, I'll need to probably just select by app and title from yabai -m query --windows, and then just minimize/deminimize based on current state right?

@dominiklohmann
Copy link
Collaborator

That's one possibility. This is why I mentioned the labelling of windows above, as that makes sorting windows into multiple "scratchpads" easier.

@hahuang65
Copy link
Author

Hmm, so personally, for me, I'm not sure I'll need anything beyond just the title since I can title my iTerm2 windows. But yeah, I can see why tagging may be useful to someone else.

@hahuang65
Copy link
Author

Is there a way to re-size and then center a floating window?

@hahuang65
Copy link
Author

hahuang65 commented Apr 20, 2020

Here's my solution... please let me know if this works for you @sainathadapa...
Also, suggestions and optimizations are welcome!

#!/usr/bin/env bash

scratchpad_id=$(yabai -m query --windows | jq '.[] | select(.title=="Scratchpad").id')

if [[ "$scratchpad_id" -lt 1 ]]; then
  scratchpad_id=$(iterm Scratchpad | awk '{print $NF}')
  sleep 1
  yabai -m window --focus "$scratchpad_id"
  yabai -m window --toggle float
  yabai -m window --resize abs:1920:1080
  yabai -m window --move abs:960:540
else
  is_minimized=$(yabai -m query --windows --window "$scratchpad_id" | jq '.minimized')
  current_space=$(yabai -m query --spaces --space | jq '.index')

  if [[ "$is_minimized" -eq 1 ]]; then
    yabai -m window "$scratchpad_id" --space "$current_space"
    yabai -m window --focus "$scratchpad_id"
  else
    yabai -m window "$scratchpad_id" --minimize
  fi
fi

@hahuang65
Copy link
Author

note iterm Scratchpad is a custom Applescript I wrote to start iTerm with the Scratchpad profile.

@ahmedakef
Copy link

@hahuang65 may you share the apple script?
and how to where did you put the code that you shared?

@hahuang65
Copy link
Author

@hahuang65 may you share the apple script? and how to where did you put the code that you shared?

I haven't used iterm in a LONG time, but this is the script from my git history

#!/usr/bin/osascript

on profileInactive(profileName)
  if application "iTerm" is running then
    tell application "iTerm"
      repeat with aWindow in windows
        tell aWindow
          tell current session
            set profName to profile name
            if profName is profileName then
              return false
            end if
          end tell
        end tell
      end repeat
    end tell
  end if

  return true
end profileExists

on startProfile(profileName)
  if profileName is "Default" then
    if application "iTerm" is running then
      tell application "iTerm"
        create window with profile profileName
      end tell
    else
      tell application "iTerm"
        activate
      end tell
    end
  else if profileName is "Notepad" then
    if application "iTerm" is running then
      if profileInactive("Notepad") then
        tell application "iTerm"
          create window with profile "Notepad" command "/usr/local/bin/emacs ~/.org/Main.org"
        end tell
      end if
    else
      tell application "iTerm"
        tell current session of current window
          close
        end tell
        create window with profile "Notepad" command "/usr/local/bin/emacs ~/.org/Main.org"
      end tell
    end
  else if profileName is "Scratchpad" then
    if application "iTerm" is running then
      if profileInactive("Scratchpad") then
        tell application "iTerm"
          create window with profile "Scratchpad"
        end tell
      end if
    else
      tell application "iTerm"
        tell current session of current window
          close
        end tell
        create window with profile "Scratchpad"
      end tell
    end
  end if
end startProfile

on run argList
  set profileName to item 1 of argList
  startProfile(profileName)
end

@koekeishiya
Copy link
Owner

Scratchpad implemented on master for next release: #2203 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
suggestion Request for new feature or some form of enhancement
Projects
None yet
Development

No branches or pull requests

5 participants