Open dalyIsaac opened 11 months ago
On the topic of commands, I think we can benefit from allowing commands to accept parameters and return results. As is, they're just invoked nominally. Works fine, but leads to awkward workarounds like this:
// Set up workspaces.
const int numWorkspaces = 12;
for(var i = 1; i <= numWorkspaces; i++) {
context.WorkspaceManager.Add($"{i}");
if(i > 10) {
continue;
}
var vk = VIRTUAL_KEY.VK_0 + (ushort)(i%10);
var idx = i;
context.KeybindManager.SetKeybind(
$"whim.core.activate_workspace_{idx}",
new Keybind(IKeybind.Win, vk));
context.CommandManager.Add($"move_window_to_workspace_{idx}", $"Move window to workspace {idx}",
() => {
var workspaces = context.WorkspaceManager.ToArray();
context.WorkspaceManager.MoveWindowToWorkspace(workspaces[idx-1]);
});
context.KeybindManager.SetKeybind(
$"whim.custom.move_window_to_workspace_{idx}",
new Keybind(IKeybind.WinShift, vk));
}
for(var i = 11; i <= numWorkspaces; i++) {
var idx = i;
context.CommandManager.Add($"activate_workspace_{idx}", $"Activate workspace {idx}",
() => {
var workspaces = context.WorkspaceManager.ToArray();
context.WorkspaceManager.Activate(workspaces[idx-1]);
});
context.CommandManager.Add($"move_window_to_workspace_{idx}", $"Move window to workspace {idx}",
() => {
var workspaces = context.WorkspaceManager.ToArray();
context.WorkspaceManager.MoveWindowToWorkspace(workspaces[idx-1]);
});
}
context.KeybindManager.SetKeybind("whim.custom.activate_workspace_11",
new Keybind(IKeybind.Win, VIRTUAL_KEY.VK_OEM_7)); // quote
context.KeybindManager.SetKeybind("whim.custom.move_window_to_workspace_11",
new Keybind(IKeybind.WinShift, VIRTUAL_KEY.VK_OEM_7)); // quote
context.KeybindManager.SetKeybind("whim.custom.activate_workspace_12",
new Keybind(IKeybind.Win, VIRTUAL_KEY.VK_OEM_5)); // backslash
context.KeybindManager.SetKeybind("whim.custom.move_window_to_workspace_12",
new Keybind(IKeybind.WinShift, VIRTUAL_KEY.VK_OEM_5)); // backslash
Not a showstopper, but if Whim introduces IPC, I think it'd be easier to rethink how Commands work before IPC/RPC implementation.
Question: can/should the IPC be implemented as a plugin? My brain kinda sees it as a binding to the CommandManager. So a plugin could take care of marshalling bytes in and out of the process and just glue it to the ICommandManager methods.
Question: can/should the IPC be implemented as a plugin? My brain kinda sees it as a binding to the CommandManager. So a plugin could take care of marshalling bytes in and out of the process and just glue it to the ICommandManager methods.
I think we're reasoning along a similar line. My loose initial idea was that the plugin would:
I was leaning towards having the new commands being specific to the plugin where they wouldn't be a formal part of the core commands interface, but perhaps there's a case for having them in the core.
Another thing I haven't thought through at all is what sort of IPC would be used (named pipes, TCP, web sockets, gRPC, SignalR).
Whim will transition to an IPC message-passing model for plugins. This will enable the following scenarios:
IPC will occur using name pipes.
Tasks
Transform
serialization and deserializationPicker
serialization and deserializationCommand
serialization and deserializationNamedPipe
client and server classesNamedPipe
serverPlugins
Whim.FocusIndicator
to a new STAWhim.Bar
to a new STAWhim.CommandPalette
to a new STAWhim.FloatingLayout
to a new STAWhim.Gaps
to a new STAWhim.LayoutPreview
to a new STAWhim.SliceLayout
to a new STAWhim.TreeLayout
to a new STAWhim.TreeLayout.Bar
to a new STAWhim.TreeLayout.CommandPalette
to a new STAWhim.Updater
to a new STA