Commit graph

12 commits

Author SHA1 Message Date
Leon Liang a0edb12cd6
Add Minimize to Tray and Tray Icon (#10368)
A brief summary of the behavior of the tray icon:
- There will only ever be one tray icon representing all windows.
- Left-Click on a Tray Icon brings up the MRU window.
- Right-Click on a Tray Icon brings up a Context Menu:
```
Focus Terminal
----------------
Windows --> Window ID 1 - <unnamed window>
            Named Window
            Named Window Again
 ```
- Focus Terminal will bring up the MRU window.
- Clicking on any of the Window "names" in the submenu will summon the window.

## Settings Changes

Two new global settings are introduced: `alwaysShowTrayIcon` and `minimizeToTray`. Here's a chart explaining the behavior with the two settings.

|                      | `alwaysShowTrayIcon:true`                                          | `alwaysShowTrayIcon:false`                                         |
|----------------------|------------------------------------------------------------------|------------------------------------------------------------------|
| `minimizeToTray:true`  | tray icon is always shown. minimize button will hide the window. | tray icon is always shown. minimize button will hide the window. |
| `minimizeToTray:false` | tray icon is always shown.                                       | tray icon is not shown ever.                                     |

Closes #5727

## References
[Spec for Minimize to Tray](https://github.com/microsoft/terminal/blob/main/doc/specs/%23653%20-%20Quake%20Mode/%23653%20-%20Quake%20Mode.md#minimize-to-tray)
Docs PR - MicrosoftDocs/terminal#352
#10448 - My list of TODOs
2021-08-12 19:54:39 +00:00
Mike Griese 3866771b1b
Add "monitor": "any"|"toCurrent"|"toMouse" setting to globalSummon (#10092)
#### ⚠️ this pr targets #9977

## Summary of the Pull Request

This adds support for part of the `monitor` property for `globalSummon`. It also goes a little off-spec:

```json
"monitor": "any"|"toCurrent"|"toMouse"
```

* `monitor`: This controls the monitor that the window will be summoned from/to
  - `"any"`: Summon the MRU window, regardless of which monitor it's currently on.
  - `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor with the current **foreground** window.
  - [**NEW**] `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse** cursor is.

When I was playing with this, It felt like `toMouse` was always what I wanted, not `toCurrent`. We can always just comment that out if we think that's contentious - I'm aware I didn't originally spec that.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-60325291
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated 😢 

## Detailed Description of the Pull Request / Additional comments

I made `toMouse` the default because it felt better. fite-me.jpg 

## Validation Steps Performed
my ever evolving blob:

```jsonc
    { "keys": "ctrl+`", "command": { "action": "quakeMode" } },
    { "keys": "ctrl+1", "command": { "action": "globalSummon" } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
    // { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
    { "keys": "ctrl+2", "command": { "action": "globalSummon", "monitor": "any" } },
    // { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
    { "keys": "ctrl+3", "command": { "action": "globalSummon", "monitor": "toMouse" } },
    // { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
    { "keys": "ctrl+4", "command": { "action": "globalSummon", "monitor": "toMouse", "dropdownDuration": 500 } },
    { "keys": "ctrl+5", "command": { "action": "globalSummon", "dropdownDuration": 500 } },
```
2021-05-17 12:57:08 +00:00
Mike Griese 6e11780ca6
Add property to control dropdown speed of global summon (#9977)
## Summary of the Pull Request

Adds the `dropdownDuration` property to `globalSummon`. This controls how fast the window appears on the screen when summoned from minimized. It similarly controls the speed for sliding out of view when the window is dismissed with `"toggleVisibility": true`.

`dropdownDuration` specifies the duration in **milliseconds**. This defaults to `0` for `globalSummon`, and defaults to `200` for `quakeMode`. 200 was picked because, according to [`AnimateWindow`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-animatewindow): 

>  Typically, an animation takes 200 milliseconds to play.

Do note that you won't be able to interact with the window during the animation! Input sent during the dropdown will arrive at the end of the animation, but input sent during the slide-up _won't_. Avoid setting this to large values!

The gifs are in Teams. 

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-59030824
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I had the following previously in the doc comments, but it feels better in the PR body:

- This was chosen because it was easier to implement and generally nicer than:
  * `AnimateWindow`, which would show the window borders for the duration of
    the animation, and occasionally just plain not work. Additionally, for
    `AnimateWindow` to work, the window much not be visible, so we'd need to
    first restore the window, then hide it, then animate it. That would flash
    the taskbar.
  * `SetWindowRgn` on the root HWND, which caused the xaml content to shift to
    the left, and caused a black bar to be drawn on the right of the window.
    Presumably, `SetWindowRgn` and `DwmExtendFrameIntoClientArea` did not play
    well with each other.
  * `SetWindowPos(..., SWP_NOSENDCHANGING)`, which worked the absolute best for
    longer animations, and is the closest to the actual implementation of
    `AnimateWindow`. This would resize the ROOT window, without sending resizes
    to the XAML island, allowing the content to _not_ reflow. but for a
    duration of 200ms, would only ever display ~2 frames. That's basically
    not even animation anymore, it's now just an "appear". Since that's how
    long the default animation is, if felt silly to have it basically not
    work by default.
- If a future reader would like to implement this better, **they should feel
  free to**, and not mistake my notes here as expertise. These are research
  notes into the dark and terrible land that is Win32 programming. I'm no expert. 

## Validation Steps Performed

This is the blob of json I'm testing with these days:

```jsonc
        { "keys": "ctrl+`", "command": { "action": "quakeMode" } },
        { "keys": "ctrl+1", "command": { "action": "globalSummon" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "desktop": "toCurrent" } },
        // { "keys": "ctrl+2", "command": { "action": "globalSummon", "toggleVisibility": false } },
        { "keys": "ctrl+2", "command": { "action": "globalSummon", "dropdownDuration": 2000 } },
        { "keys": "ctrl+3", "command": { "action": "globalSummon", "desktop": "onCurrent" } },
        { "keys": "ctrl+4", "command": { "action": "globalSummon", "desktop": "any" } },
```

* <kbd>ctrl+\`</kbd> will summon the quake window with a _quick_ animation
* <kbd>ctrl+2</kbd> will summon the window with a  s l o w  animation
2021-05-17 07:28:46 -05:00
Mike Griese 30d2d2c76d
When the window is summoned and is already active, minimize it. (#9963)
This adds a `toggleVisibility` parameter to `globalSummon`. 
* When `true` (default): when you press the global summon keybinding, and the window is currently the foreground window, we'll minimize the window.
* When `false`, we'll just do nothing.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks a box in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030814
* [x] I work here
* [ ] No tests for this one.
* [ ] yes yes eventually I'll come back on the docs

## Detailed Description of the Pull Request / Additional comments

I've got nothing extra to add here. This one's pretty simple. I'm only targeting #9954 since that one laid so much foundation to build on, with the `SummonBehavior`

## Validation Steps Performed

Played with this for a while, and it's amazing.
2021-04-28 18:57:14 -05:00
Mike Griese 65b22b9abb
Add desktop param to globalSummon; set _quake = toCurrent (#9954)
This adds support for the `desktop` param to the `globalSummon` action. It accepts 3 values:
* `toCurrent` (default): The window moves to the current desktop when it's summoned
* `any`: We don't care what desktop the window is on. We'll go to the desktop the window is on when we summon it.
* `onCurrent`: We'll only try to summon the MRU window on this desktop when summoning a window. 
  * When combined with `name`, if there's a window matching `name`, we'll move it to this desktop. 
  * If there's not a window on this desktop, and `name` is omitted, then we'll make a new window.

`quakeMode` was also updated to use `toCurrent` behavior by default.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks some boxes in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030845
* [x] I work here
* [x] Tests added 
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

S/O to https://github.com/microsoft/PowerToys, who graciously let us use `VirtualDesktopUtils` for figuring out what desktop is the current desktop. Yea, that's all we needed that entire file for. No, there isn't an API for this (_surprised-pikachu.png_)

## Validation Steps Performed

Played with this for a while, and it's amazing.
2021-04-28 17:25:48 -05:00
Mike Griese d08271e734
Add globalSummon action (#9854)
Adds support for two new actions:
* `globalSummon`, which can be used to activate a window using a _global_ (READ: OS-level) hotkey.
  - accepts an optional `name` argument. When provided, this will attempt to summon with the given name. When omitted, we'll try to summon the most recent window.
* `quakeMode` which is `globalSummon` for the `_quake` window.

These actions are stored in the actions array, but are read by the `WindowsTerminal` level and bound to the OS in `IslandWindow`. The monarch registers for these keybindings with the OS. When one is pressed, the monarch will recieve a `WM_HOTKEY` message. It'll use that to look up the corresponding action args. It'll use those to try and summon the right window.

## References

* #8888: Quake mode megathread
* #9274: Spec (**guys seriously i just need one more ✔️**)
* #9785: The start of granting "\_quake" super powers

## PR Checklist
* [x] Closes #653 - I'm gonna say this closes it for now, though we have _many_ follow-ups in #8888
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed

* Validated that it works with `win` keys
* Validated that it works without `win` keys
* Validated that it hot-reloads
* Validated that it moves to the new monarch
* Validated that you can bind both `globalSummon` and `quakeMode` at the same time and do different things
* Validated that you can bind `globalSummon` with a name and it creates that name if it doesn't already exist
2021-04-28 17:13:28 -05:00
Mike Griese fb597ed304
Add support for renaming windows (#9662)
## Summary of the Pull Request

This PR adds support for renaming windows.

![window-renaming-000](https://user-images.githubusercontent.com/18356694/113034344-9a30be00-9157-11eb-9443-975f3c294f56.gif)
![window-renaming-001](https://user-images.githubusercontent.com/18356694/113034452-b5033280-9157-11eb-9e35-e5ac80fef0bc.gif)


It does so through two new actions:
* `renameWindow` takes a `name` parameter, and attempts to set the window's name
  to the provided name. This is useful if you always want to hit <kbd>F3</kbd>
  and rename a window to "foo" (READ: probably not that useful)
* `openWindowRenamer` is more interesting: it opens a `TeachingTip` with a
  `TextBox`. When the user hits Ok, it'll request a rename for the provided
  value. This lets the user pick a new name for the window at runtime.

In both cases, if there's already a window with that name, then the monarch will
reject the rename, and pop a `Toast` in the window informing the user that the
rename failed. Nifty!

## References
* Builds on the toasts from #9523
* #5000 - process model megathread

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-50771747
* [x] I work here
* [x] Tests addded (and pass with the help of #9660)
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I'm sending this PR while finishing up the tests. I figured I'll have time to sneak them in before I get the necessary reviews.

> PAIN: We can't immediately focus the textbox in the TeachingTip. It's
> not technically focusable until it is opened. However, it doesn't
> provide an even tto tell us when it is opened. That's tracked in
> microsoft/microsoft-ui-xaml#1607. So for now, the user _needs_ to
> click on the text box manually.
> We're also not using a ContentDialog for this, because in Xaml
> Islands a text box in a ContentDialog won't recieve _any_ keypresses.
> Fun!

## Validation Steps Performed

I've been playing with 

```json
        { "keys": "f1", "command": "identifyWindow" },
        { "keys": "f2", "command": "identifyWindows" },
        { "keys": "f3", "command": "openWindowRenamer" },
        { "keys": "f4", "command": { "action": "renameWindow", "name": "foo" } },
        { "keys": "f5", "command": { "action": "renameWindow", "name": "bar" } },
```

and they seem to work as expected
2021-04-02 16:00:04 +00:00
Mike Griese 03ea0f49ad
Add an action for identifying windows (#9523)
## Summary of the Pull Request

This is a follow up to #9300. Now that we have names on our windows, it would be nice to see who is named what. So this adds two actions:

* `identifyWindow`: This action will pop up a little toast (#8592) displaying the name and ID of the window, and is bound by default.
![identify-window-toast-000](https://user-images.githubusercontent.com/18356694/111529085-bf710580-872f-11eb-8880-b0b617596cfc.gif)

* `identifyWindows`: This action will request that ALL windows pop up that toast. This is meant to feel like the "Identify" button on the Windows display settings. However, sometimes, it's wonky. 
  ![teaching-tip-dismiss-001](https://user-images.githubusercontent.com/18356694/111529292-fe06c000-872f-11eb-8d4a-5688e4ce1175.gif)
  That's being tracked upstream on https://github.com/microsoft/microsoft-ui-xaml/issues/4382
  Because it's so wonky, we won't bind that by default. Maybe if we get that fixed, then we'll change the default binding from `identifyWindow` to `identifyWindows`


## References

## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/projects/5#card-51431492
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

You may note that there are some macros to make interacting with lots and lots of actions easier. There's a lot of boilerplate whenever you need to make a new action, so I thought: "Can we make that easier?" 

Turns out you can make it a _LOT_ easier, but that work is still behind another PR after this one. Get excited
2021-03-30 16:08:03 +00:00
Mike Griese 43c469fc95
Add support for naming windows with the -w parameter (#9300)
This finishes the implementation of `--window` to also accept a string
as the "name" of the window. So you can say 

```sh
wt -w foo new-tab
wt -w foo split-pane
```

and have both those commands execute in the same window, the one named
"foo". This is just slightly more ergonomic than manually using the IDs
of windows. In the future, I'll be working on renaming windows, and
displaying these names. 

> #### `--window,-w <window-id>`
> Run these commands in the given Windows Terminal session. This enables opening
> new tabs, splits, etc. in already running Windows Terminal windows.
> * If `window-id` is `0`, run the given commands in _the current window_.
> * If `window-id` is a negative number, or the reserved name `new`, run the
>   commands in a _new_ Terminal window.
> * If `window-id` is the ID or name of an existing window, then run the
>   commandline in that window.
> * If `window-id` is _not_ the ID or name of an existing window, create a new
>   window. That window will be assigned the ID or name provided in the
>   commandline. The provided subcommands will be run in that new window.
> * If `window-id` is omitted, then obey the value of `windowingBehavior` when
>   determining which window to run the command in.

Before this PR, I think we didn't actually properly support assigning
the id with `wt -w 12345`. If `12345` didn't exist, it would make a new
window, but just assign it the next id, not assign it 12345.

## References
* #4472, #8135
* https://github.com/microsoft/terminal/projects/5

## Validation Steps Performed
Ran tests
Messed with naming windows, working as expected.

Closes https://github.com/microsoft/terminal/projects/5#card-51431478
2021-03-17 19:28:01 +00:00
Mike Griese 69318d3ba1
Add support for the windowingBehavior setting (#9118)
Adds support for the `windowingBehavior` global setting. This setting
controls how mutiple instances of `wt` behave in the absence of the `-w`
parameter. This setting has three values:
* `"useNew"`: (default) Multiple `wt` invocations (without the `-w`
  param) always create new windows. 
* `"useAnyExisting"`: When starting a new `wt`, we'll instead default to
  any existing windows. `wt -w -1` will still create new windows. 
* `"useExisting"`: Similar to `useAnyExisting`, but limits to
  windows on the current desktop. 

The IVirtualDesktopManager interface is _very_ limited. Hence why we
have to track the HWNDs manually, and ask if they're on the current
desktop. 

## Validation Steps Performed
I've been playing with it for a week now. 

References #5000
References projects/5
References #8898
Spec'd in #8135
Closes #2227
Closes https://github.com/microsoft/terminal/projects/5#card-51431448
Closes https://github.com/microsoft/terminal/projects/5#card-51431433
2021-02-19 21:09:17 +00:00
Mike Griese 03ebe514e9
Add support for running a commandline in another WT window (#8898)
## Summary of the Pull Request

**If you're reading this PR and haven't signed off on #8135, go there first.**

![window-management-000](https://user-images.githubusercontent.com/18356694/103932910-25199380-50e8-11eb-97e3-594a31da62d2.gif)

This provides the basic parts of the implementation of #4472. Namely:
* We add support for the `--window,-w <window-id>` argument to `wt.exe`, to allow a commandline to be given to another window.
    * If `window-id` is `0`, run the given commands in _the current window_.
    * If `window-id` is a negative number, run the commands in a _new_ Terminal window.
    * If `window-id` is the ID of an existing window, then run the commandline in that window.
    * If `window-id` is _not_ the ID of an existing window, create a new window. That window will be assigned the ID provided in the commandline. The provided subcommands will be run in that new window.
    * If `window-id` is omitted, then create a new window.


## References
* Spec: #8135
* Megathread: #5000
* Project: projects/5

## PR Checklist
* [x] Closes #4472
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **sure does**

## Detailed Description of the Pull Request / Additional comments

Note that `wt -w 1 -d c:\foo cmd.exe` does work, by causing window 1 to change 

There are limitations, and there are plenty of things to work on in the future:
* [ ] We don't support names for windows yet
* [ ] We don't support window glomming by default, or a setting to configure what happens when `-w` is omitted. I thought it best to lay the groundwork first, then come back to that.
* [ ] `-w 0` currently just uses the "last activated" window, not "the current". There's more follow-up work to try and smartly find the actual window we're being called from.
* [ ] Basically anything else that's listed in projects/5.

I'm cutting this PR where it currently is, because this is already a huge PR. I believe the remaining tasks will all be easier to land, once this is in. 

## Validation Steps Performed

I've been creating windows, and closing them, and running cmdlines for a while now. I'm gonna keep doing that while the PR is open, till no bugs remain.

# TODOs
* [x] There are a bunch of `GetID`, `GetPID` calls that aren't try/caught 😬 
  -  [x] `Monarch.cpp`
  -  [x] `Peasant.cpp`
  -  [x] `WindowManager.cpp`
  -  [x] `AppHost.cpp`
* [x] If the monarch gets hung, then _you can't launch any Terminals_ 😨 We should handle this gracefully.
  - Proposed idea: give the Monarch some time to respond to a proposal for a commandline. If there's no response in that timeframe, this window is now a _hermit_, outside of society entirely. It can't be elected Monarch. It can't receive command lines. It has no ID.  
  	- Could we gracefully recover from such a state? maybe, probably not though.
    -  Same deal if a peasant hangs, it could end up hanging the monarch, right? Like if you do `wt -w 2`, and `2` is hung, then does the monarch get hung waiting on the hung peasant?
  - After talking with @miniksa, **we're gonna punt this from the initial implementation**. If people legit hit this in the wild, we'll fix it then.
2021-02-10 11:28:09 +00:00
Mike Griese 7d503a4352
Add Microsoft.Terminal.Remoting.dll (#8607)
Adds a `Microsoft.Terminal.Remoting.dll` to our solution. This DLL will
be responsible for all the Monarch/Peasant work that's been described in
#7240 & #8135. 

This PR does _not_ implement the Monarch/Peasant architecture in any
significant way. The goal of this PR is to just to establish the project
layout, and the most basic connections. This should make reviewing the
actual meat of the implementation (in a later PR) easier. It will also
give us the opportunity to include some of the basic weird things we're
doing (with `CoRegisterClass`) in the Terminal _now_, and get them
selfhosted, before building on them too much.

This PR does have windows registering the `Monarch` class with COM. When
windows are created, they'll as the Monarch if they should create a new
window or not. In this PR, the Monarch will always reply "yes, please
make a new window".

Similar to other projects in our solution, we're adding 3 projects here:
* `Microsoft.Terminal.Remoting.lib`: the actual implementation, as a
  static lib.
* `Microsoft.Terminal.Remoting.dll`: The implementation linked as a DLL,
  for use in `WindowsTerminal.exe`.
* `Remoting.UnitTests.dll`: A unit test dll that links with the static
  lib. 

There are plenty of TODOs scattered about the code. Clearly, most of
this isn't implemented yet, but I do have more WIP branches. I'm using
[`projects/5`](https://github.com/microsoft/terminal/projects/5) as my
notation for TODOs that are too small for an issue, but are part of the
whole Process Model 2.0 work.

## References

* #5000 - this is the process model megathread
* #7240 - The process model 2.0 spec.
* #8135 - the window management spec. (please review me, I have 0/3
  signoffs even after the discussion we had 😢)
* #8171 - the Monarch/peasant sample. (please review me, I have 1/2)

## PR Checklist
* [x] Closes nothing, this is just infrastructure
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
2021-01-07 22:59:37 +00:00