Skip to content

Add zoomLeft: / zoomRight: / macOS 13 Stage Manager actions #1330

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

Merged
merged 1 commit into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions runtime/doc/gui_mac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -446,13 +446,13 @@ that is the action that instructs them to paste something.)
Menus are configured using the |:macmenu| command and the |:macaction| command
can be used to send action messages.

*:maca* *:macaction*
:maca[ction] {action:} Send the message "action:" to the first responder.
The list of allowed actions can be seen by typing
*E9001-M* *:maca* *:macaction*
:maca[ction] {action:} Send the message "action:" to the first responder in
MacVim. The list of allowed actions can be seen by
typing >
:maca <C-d>
An attempt to send an action not listed here will
result in an error. This list is specified in a
property list file called |Actions.plist|.
< An attempt to send an action not listed here will
result in an error. See |macvim-actions| below.

*:macm* *:macmenu*
:macm[enu] {menu} {key}={arg} ...
Expand All @@ -466,10 +466,10 @@ can be used to send action messages.

For convenience, a menu with "action=name:" which is
bound to <Nop> will act as if bound to
":maca name:<CR>". Thus, if "Menu.Item" is given by
":maca name:<CR>". Thus, if "Menu.Item" is given by >
:an Menu.Item <Nop>
:macm Menu.Item action=name:
then ":emenu Menu.Item" is equivalent to
< then ":emenu Menu.Item" is equivalent to
":maca name:".

The key equivalent is specified with the <D-..>
Expand Down Expand Up @@ -513,18 +513,17 @@ file for more examples on how to set up menus. Note: When no window is open a
minimal default menu is used. The default menu is set up in MainMenu.nib
which resides in "Resources/English.lproj/" folder inside the app bundle.

*E9001-M* *Actions.plist*
Some action messages would not be suitable to call from within Vim, so there
is a dictionary called "Actions.plist" (in the Resources folder of the
application bundle) which contains all actions that may be called. The key in
this dictionary is the name of the action message (case sensitive), the value
is not used.
*Actions.plist* *macvim-actions*
Some actions (e.g. changing the font size) are not directly Vim related, and
are handled by MacVim on the application level for the GUI. MacVim allows
these actions to be invoked by either directly calling |:macaction| or binding
to a menu via |:macmenu|. The full list of actions can be found in the file
"Actions.plist" (under MacVim.app/Contents/Resources/), but below are the
common ones which might be useful.

Hint: The |:macaction| command supports command-line completion so you can
enter ":maca<Space><C-d>" to see a list of all available actions.

Here are some of the actions from Actions.plist which might be useful.

Action Description ~
fileOpen: Show "File Open" dialog
findNext: Search forward using the "Find Pasteboard"
Expand All @@ -543,8 +542,14 @@ performMiniaturize: Minimize window to the dock
performZoom: Zoom window (same as clicking the green blob)
terminate: Quit MacVim
zoomAll: Zoom all windows
zoomLeft: Pin the window to the left of the screen
zoomRight: Pin the window to the right of the screen
_cycleWindows: Select next window (similar to <D-`>)
_cycleWindowsBackwards: Select previous window (similar to <D-S-`>)
_removeWindowFromStageManagerSet Remove window from a Stage Manager Set. Same
as the "Remove Window from Set" menu item.
joinAllStageManagerSets Window will float among all Stage Manager sets
unjoinAllStageManagerSets Window will only show up in its own set

==============================================================================
7. Toolbar *macvim-toolbar*
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/tags
Original file line number Diff line number Diff line change
Expand Up @@ -8371,6 +8371,7 @@ macintosh os_mac.txt /*macintosh*
macro map.txt /*macro*
macvim gui_mac.txt /*macvim*
macvim-PATH gui_mac.txt /*macvim-PATH*
macvim-actions gui_mac.txt /*macvim-actions*
macvim-appearance gui_mac.txt /*macvim-appearance*
macvim-appearance-mode gui_mac.txt /*macvim-appearance-mode*
macvim-autocommands gui_mac.txt /*macvim-autocommands*
Expand Down
5 changes: 3 additions & 2 deletions runtime/menu.vim
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,16 @@ if has("gui_macvim")
an <silent> 9998.301 Window.Minimize\ All <Nop>
an <silent> 9998.310 Window.Zoom <Nop>
an <silent> 9998.311 Window.Zoom\ All <Nop>
an 9998.318 Window.-SEP1- <Nop>
an <silent> 9998.320 Window.Toggle\ Full\ Screen\ Mode :set invfullscreen<CR>
tln <silent> 9998.320 Window.Toggle\ Full\ Screen\ Mode <C-W>:set invfullscreen<CR>
an 9998.330 Window.-SEP1- <Nop>
an 9998.330 Window.-SEP2- <Nop>
" TODO! Grey out if no tabs are visible.
an <silent> 9998.340 Window.Show\ Next\ Tab :tabnext<CR>
tln <silent> 9998.340 Window.Show\ Next\ Tab <C-W>:tabnext<CR>
an <silent> 9998.350 Window.Show\ Previous\ Tab :tabprevious<CR>
tln <silent> 9998.350 Window.Show\ Previous\ Tab <C-W>:tabprevious<CR>
an 9998.360 Window.-SEP2- <Nop>
an 9998.360 Window.-SEP3- <Nop>
an <silent> 9998.370 Window.Bring\ All\ To\ Front <Nop>
an <silent> 9998.380 Window.Stay\ in\ Front <Nop>
an <silent> 9998.390 Window.Stay\ in\ Back <Nop>
Expand Down
10 changes: 10 additions & 0 deletions src/MacVim/Actions.plist
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,21 @@
<string></string>
<key>zoomAll:</key>
<string></string>
<key>zoomLeft:</key>
<string></string>
<key>zoomRight:</key>
<string></string>
<key>stayInFront:</key>
<string></string>
<key>stayInBack:</key>
<string></string>
<key>stayLevelNormal:</key>
<string></string>
<key>_removeWindowFromStageManagerSet:</key>
<string></string>
<key>joinAllStageManagerSets:</key>
<string></string>
<key>unjoinAllStageManagerSets:</key>
<string></string>
</dict>
</plist>
8 changes: 6 additions & 2 deletions src/MacVim/MMWindowController.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
int updateToolbarFlag;
BOOL keepOnScreen;
NSString *windowAutosaveKey;
BOOL fullScreenEnabled;
MMFullScreenWindow *fullScreenWindow;
BOOL fullScreenEnabled; ///< Whether full screen is on (native or not)
MMFullScreenWindow *fullScreenWindow; ///< The window used for non-native full screen. Will only be non-nil when in non-native full screen.
int fullScreenOptions;
BOOL delayEnterFullScreen;
NSRect preFullScreenFrame;
Expand Down Expand Up @@ -127,5 +127,9 @@
- (IBAction)fontSizeDown:(id)sender;
- (IBAction)findAndReplace:(id)sender;
- (IBAction)zoom:(id)sender;
- (IBAction)zoomLeft:(id)sender;
- (IBAction)zoomRight:(id)sender;
- (IBAction)joinAllStageManagerSets:(id)sender;
- (IBAction)unjoinAllStageManagerSets:(id)sender;

@end
57 changes: 57 additions & 0 deletions src/MacVim/MMWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,64 @@ - (IBAction)zoom:(id)sender
[vimController sendMessage:ZoomMsgID data:data];
}

/// Pin the window to the left of the screen.
///
/// @note We expose this as a method instead of just having Actions.plist
/// expose NSWindow's private API `_zoomLeft` because it's a little nicer this
/// way instead of having to confuse the user with the underscore, and also so
/// that we can block this while full screen is active.
- (IBAction)zoomLeft:(id)sender
{
if (fullScreenEnabled)
return;

// macOS (as of 13.0) doesn't currently have an API to do "zoom left/right"
// aka Aero Snap in Windows, even though macOS 10.15 added UI to do so if
// you hover over the full screen button with Option key pressed. Because
// of that, we have to cheat a little bit and use private APIs
// (_zoomLeft/_zoomRight) which seems to work just fine. We also
// future-proof by detecting if this API gets graduated to public API
// (without the "_") and call that if that exists.
if ([decoratedWindow respondsToSelector:@selector(zoomLeft:)]) {
[decoratedWindow performSelector:@selector(zoomLeft:) withObject:sender];
} else if ([decoratedWindow respondsToSelector:@selector(_zoomLeft:)]) {
[decoratedWindow performSelector:@selector(_zoomLeft:) withObject:sender];
}
}

/// Pin the window to the right of the screen. See zoomLeft: for comments.
- (IBAction)zoomRight:(id)sender
{
if (fullScreenEnabled)
return;

if ([decoratedWindow respondsToSelector:@selector(zoomRight:)]) {
[decoratedWindow performSelector:@selector(zoomRight:) withObject:sender];
} else if ([decoratedWindow respondsToSelector:@selector(_zoomRight:)]) {
[decoratedWindow performSelector:@selector(_zoomRight:) withObject:sender];
}
}

/// Make this window join all app sets
- (IBAction)joinAllStageManagerSets:(id)sender
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_13_0
if (@available(macos 13.0, *)) {
[decoratedWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllApplications];
}
#endif
}

/// Make this window only show up in its own set. This is the default, so calling
/// this is only necessary if joinAllStageManagerSets: was previousaly called.
- (IBAction)unjoinAllStageManagerSets:(id)sender
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_13_0
if (@available(macos 13.0, *)) {
[decoratedWindow setCollectionBehavior:NSWindowCollectionBehaviorPrimary];
}
#endif
}

// -- Services menu delegate -------------------------------------------------

Expand Down