Whim icon indicating copy to clipboard operation
Whim copied to clipboard

IPC

Open dalyIsaac opened this issue 2 years ago • 2 comments

Whim will transition to an IPC message-passing model for plugins. This will enable the following scenarios:

  • External plugins to Whim
  • Whim plugins to avoid congesting the main Whim thread when handling events

IPC will occur using name pipes.

Tasks

  • [ ] Add Transform serialization and deserialization
  • [ ] Add Picker serialization and deserialization
  • [ ] Add Command serialization and deserialization
  • [ ] Add NamedPipe client and server classes
  • [ ] Add event emitter to NamedPipe server

Plugins

  • [ ] Move Whim.FocusIndicator to a new STA
  • [ ] Move Whim.Bar to a new STA
  • [ ] Move Whim.CommandPalette to a new STA
  • [ ] Move Whim.FloatingLayout to a new STA
  • [ ] Move Whim.Gaps to a new STA
  • [ ] Move Whim.LayoutPreview to a new STA
  • [ ] Move Whim.SliceLayout to a new STA
  • [ ] Move Whim.TreeLayout to a new STA
  • [ ] Move Whim.TreeLayout.Bar to a new STA
  • [ ] Move Whim.TreeLayout.CommandPalette to a new STA
  • [ ] Move Whim.Updater to a new STA

dalyIsaac avatar Dec 04 '23 11:12 dalyIsaac

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.

gplusplus314 avatar Dec 07 '23 00:12 gplusplus314

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:

  • expose the existing commands to perform actions
  • support a new type of command (command request?) to retrieve data
  • support another new type of command which would accept arguments

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).

dalyIsaac avatar Dec 07 '23 09:12 dalyIsaac