Skip to content

Commit

Permalink
Merge pull request #3008 from VsVim/dev/nosami/window-management
Browse files Browse the repository at this point in the history
[VSMac] Fix split windows and tab movement commands
  • Loading branch information
nosami committed Sep 8, 2022
2 parents 3fbf0c6 + 1b7b18c commit 79f57a4
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 52 deletions.
2 changes: 1 addition & 1 deletion Src/VimMac/Properties/AddinInfo.cs
Expand Up @@ -5,7 +5,7 @@
[assembly: Addin(
"VsVim",
Namespace = "Vim.Mac",
Version = "2.8.0.16"
Version = "2.8.0.17"
)]

[assembly: AddinName("VsVim")]
Expand Down
3 changes: 3 additions & 0 deletions Src/VimMac/VimMac.csproj
Expand Up @@ -13,6 +13,9 @@
<ProjectReference Include="..\VimCore\VimCore.fsproj" />
<PackageReference Include="Microsoft.VisualStudioMac.Sdk" Version="17.0.0" />
</ItemGroup>
<ItemGroup>
<AddinReference Include="MonoDevelop.TextEditor" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
<Folder Include="Resources\" />
Expand Down
113 changes: 62 additions & 51 deletions Src/VimMac/WindowManagement.cs
Expand Up @@ -26,75 +26,86 @@ public Notebook(bool isActive, int activeTab, ImmutableArray<string> fileNames)

internal static class WindowManagement
{
const BindingFlags instanceFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private const BindingFlags instanceFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
private const BindingFlags staticFlags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;

static object[] emptyArray = Array.Empty<object>();
private static object[] emptyArray = Array.Empty<object>();
private static object shellNotebook;
private static PropertyInfo activeNotebookProperty;

static WindowManagement()
{
// CocoaWorkbenchController
var shell = GetPropertyValue(IdeApp.Workbench, "Shell");

// IShellNotebook IShell.TabControl
shellNotebook = GetPropertyValueFromInterface(shell, "IShell", "TabControl");

// SdiDragNotebook : DockNotebookController
var dockNotebookControllerType = shellNotebook.GetType().BaseType;

// public static IShellNotebook ActiveNotebook
activeNotebookProperty = dockNotebookControllerType.GetProperty("ActiveNotebook", staticFlags);
}

/// <summary>
/// Utility function to map tabs and windows into a format that we can use
/// from the Mac VimHost
/// </summary>
public static ImmutableArray<Notebook> GetNotebooks()
{
var workbench = IdeApp.Workbench.RootWindow;
var workbenchType = workbench.GetType();
var tabControlProp = workbenchType.GetProperty("TabControl", instanceFlags);
var tabControl = tabControlProp.GetValue(workbench);
var container = tabControlProp.PropertyType.GetProperty("Container", instanceFlags);
var cont = container.GetValue(tabControl, null);
var notebooks = (IEnumerable<object>)container.PropertyType.GetMethod("GetNotebooks", instanceFlags).Invoke(cont, emptyArray);
return notebooks.Select(ToNotebook).ToImmutableArray();
}
var activeNotebook = activeNotebookProperty.GetValue(shellNotebook);

private static string GetTabFileName(object tab)
{
var tabType = tab.GetType();
var fileName = (string)tabType.GetProperty("Tooltip", instanceFlags).GetValue(tab);
return fileName;
}

private static Notebook ToNotebook(object container)
{
var notebookType = container.GetType();
bool isActiveNotebook = IsActiveNotebook(container, notebookType);
// DockNotebookContainer Container { get; set; }
var container = GetPropertyValue(shellNotebook, "Container");

int currentTab = (int)notebookType.GetProperty("CurrentTabIndex", instanceFlags).GetValue(container);
// public IEnumerable<IShellNotebook> GetNotebooks()
var notebookController = GetPropertyValue(container, "NotebookController");
var getNotebooksMethod = container.GetType().GetMethod("GetNotebooks");
var notebooks = (IEnumerable<object>)getNotebooksMethod.Invoke(container, null);

var tabs = (IEnumerable<object>)notebookType.GetProperty("Tabs", instanceFlags).GetValue(container);

var files = tabs.Select(GetTabFileName).ToImmutableArray();
return notebooks.Select(ToNotebook).ToImmutableArray();

return new Notebook(isActiveNotebook, currentTab, files);
}
Notebook ToNotebook(object container)
{
var tabs = ((IEnumerable<object>)GetPropertyValue(container, "Tabs")).ToArray();
var files = tabs.Select(GetTabFileName).ToImmutableArray();
var activeTab = 0;

private static bool IsActiveNotebook(object container, Type notebookType)
{
var tabStripControllerProperty = notebookType.GetProperty("TabStripController", instanceFlags);
for(int index = 0; index < tabs.Length; index++)
{
var isActive = (bool)GetPropertyValue(tabs[index], "Active");
if (isActive)
{
activeTab = index;
break;
}
}

bool isActiveNotebook = false;
Type tabStripType;
return new Notebook(container == activeNotebook, activeTab, files);
}

if (tabStripControllerProperty != null)
string GetTabFileName(object tab)
{
var tabStripController = tabStripControllerProperty.GetValue(container);
// VSMac 8.10+
tabStripType = tabStripControllerProperty.PropertyType;
isActiveNotebook = (bool)tabStripType.GetProperty("IsActiveNotebook").GetValue(tabStripController);
return (string)GetPropertyValue(tab, "Tooltip");
}
else
{
// VSMac 8.9 and earlier
var childrenProperty = notebookType.GetProperty("Children", instanceFlags);
var children = (object[])childrenProperty.GetValue(container);
}

if (children.Length > 0)
{
var tabStrip = children[0];
tabStripType = tabStrip.GetType();
isActiveNotebook = (bool)tabStripType.GetProperty("IsActiveNotebook").GetValue(tabStrip);
}
}
return isActiveNotebook;
private static object GetPropertyValue(object o, string propertyName)
{
var objType = o.GetType();
var prop = objType.GetProperty(propertyName, instanceFlags);
var value = prop.GetValue(o);
return value;
}

private static object GetPropertyValueFromInterface(object o, string interfaceName, string propertyName)
{
var objType = o.GetType();
var interfaceType = objType.GetInterface(interfaceName);
var prop = interfaceType.GetProperty(propertyName, instanceFlags);
var value = prop.GetValue(o);
return value;
}
}
}

0 comments on commit 79f57a4

Please sign in to comment.