diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-06-10 16:50:55 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-10 16:50:55 +0200 |
| commit | b6a5ad0e5a93d9f584b3f7a0fc90f497a09cbdb0 (patch) | |
| tree | 38c77a381cfb937b428752a588c09a45c81434c9 /zellij-utils/src/plugin_api | |
| parent | feat: PWA support for the web client (#5184) (diff) | |
| download | sl0ppij-b6a5ad0e5a93d9f584b3f7a0fc90f497a09cbdb0.tar.gz sl0ppij-b6a5ad0e5a93d9f584b3f7a0fc90f497a09cbdb0.tar.xz sl0ppij-b6a5ad0e5a93d9f584b3f7a0fc90f497a09cbdb0.zip | |
Mobile layout (#5241)
* phase 2+3
* initial mobile plugin (phases 4 + 5 + 6)
* some bugfixes
* implement stage 7
* mobile interface improvements
* improve mobile pane/tab picker
* more ui improvements and fixes
* various mobile fixes
* some mobile fixes
* mobile keyboard triggering fix
* some cleanups
* initial plugin keyboard implementation
* improve keyboard hit zones
* improve keyboard
* pinch resize
* pinching fixes
* implement scrolling + panning
* initial keyboard resizing
* fix: mobile first render issues
* keyboard responsiveness
* fix some issues with the keyboard
* implement fit
* fix mobile scrolling
* add tilde cell to compact
* improve mobile keyboard
* fix starting mobile terminal font to natural keyboard size
* fix mobile resize blank screen flash
* shadow focus for mobile
* more keyboard fixes
* improve mobile status bar
* fix: render plugins to mobile clients
* allow opening new panes/tabs from the mobile plugin
* allow configuring
* fix dot slash
* improve mobile native soft keyboard interaction
* switch to native keyboard - initial implementation
* dirty hacks, but phone keyboard works now
* adjust keyboard help strip
* fix cursor in mobile
* fix keyboard and help line
* rename keyboard to modifier bar
* allow starting new session
* make clicking session name bring us to new session menu
* allow switching to desktop from the mobile ui
* mobile welcome screen initial implementation
* mobile welcome screen fixes
* various welcome screen fixes
* more mobile fixes
* moar mobile fixes
* mobile ui redesign
* fix: swallowed backspace bug
* switch session screen improvement
* touch up some interfaces
* refactor: move mobile state to own struct
* refactor: move fit resizing to the server
* remove dead flash code
* some cleanups
* refactor: clear fit on close
* refactor: improve fit api
* refactor: pane sync functions
* refactor: mouse
* refactor: break into modules
* some cleanups for the sessions screen
* fix scrolling and other stuff
* refactor: sessions screen
* refactor: panes screen
* refactor: new session screen
* refactor: menu screen
* refactor: render
* cleanups
* refactor: plugin structure
* remove unused welcome screen path
* Rename api
* refactor input.js
* cleanup useless comments
* fit/mobile refactoring
* take out the garbage
* remove more comments
* remove mobile flash on startup/attach
* fix: various mobile startup issues
* fix space bugs
* cleanup
* rustfmt
* fix windows build
* adjust modifier bar ui
* add pr
Diffstat (limited to 'zellij-utils/src/plugin_api')
| -rw-r--r-- | zellij-utils/src/plugin_api/action.proto | 2 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/action.rs | 7 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/event.proto | 9 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/event.rs | 62 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.proto | 46 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.rs | 223 |
6 files changed, 338 insertions, 11 deletions
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index 28a8337e..7eedf393 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -586,6 +586,8 @@ message MouseEventPayload { bool ctrl = 9; int64 line = 10; int64 column = 11; + bool wheel_left = 12; + bool wheel_right = 13; } message RunCommandAction { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index cd3e1522..34b3adce 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -1943,7 +1943,8 @@ impl TryFrom<Action> for ProtobufAction { | Action::SaveSession | Action::ListTabs { .. } | Action::CurrentTabInfo { .. } - | Action::SetPaneColor { .. } => Err("Unsupported action"), + | Action::SetPaneColor { .. } + | Action::ToggleMobileMode => Err("Unsupported action"), } } } @@ -2097,6 +2098,8 @@ impl TryFrom<ProtobufMouseEventPayload> for MouseEvent { middle: protobuf_event.middle as bool, wheel_up: protobuf_event.wheel_up as bool, wheel_down: protobuf_event.wheel_down as bool, + wheel_left: protobuf_event.wheel_left as bool, + wheel_right: protobuf_event.wheel_right as bool, shift: protobuf_event.shift as bool, alt: protobuf_event.alt as bool, ctrl: protobuf_event.ctrl as bool, @@ -2119,6 +2122,8 @@ impl TryFrom<MouseEvent> for ProtobufMouseEventPayload { middle: event.middle as bool, wheel_up: event.wheel_up as bool, wheel_down: event.wheel_down as bool, + wheel_left: event.wheel_left as bool, + wheel_right: event.wheel_right as bool, shift: event.shift as bool, alt: event.alt as bool, ctrl: event.ctrl as bool, diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto index 5334f434..2567c657 100644 --- a/zellij-utils/src/plugin_api/event.proto +++ b/zellij-utils/src/plugin_api/event.proto @@ -69,6 +69,7 @@ enum EventType { InitialKeybinds = 44; CommandChanged = 45; HostTerminalThemeChanged = 46; + SoftKeyboardVisibilityChanged = 47; } message EventNameList { @@ -117,6 +118,7 @@ message Event { InitialKeybindsPayload initial_keybinds_payload = 38; CommandChangedPayload command_changed_payload = 39; HostTerminalThemeChangedPayload host_terminal_theme_changed_payload = 40; + SoftKeyboardVisibilityChangedPayload soft_keyboard_visibility_changed_payload = 41; } } @@ -124,6 +126,10 @@ message HostTerminalThemeChangedPayload { HostTerminalThemeIndication mode = 1; } +message SoftKeyboardVisibilityChangedPayload { + bool visible = 1; +} + enum HostTerminalThemeIndication { Dark = 0; Light = 1; @@ -305,6 +311,8 @@ enum MouseEventName { MouseHold = 4; MouseRelease = 5; MouseHover = 6; + MouseScrollLeft = 7; + MouseScrollRight = 8; } message TabUpdatePayload { @@ -512,6 +520,7 @@ message PaneContents { optional SelectedText selected_text = 2; repeated string lines_above_viewport = 3; repeated string lines_below_viewport = 4; + optional action.Position cursor = 5; } message PaneScrollbackResponse { diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs index af421fac..5ba106d0 100644 --- a/zellij-utils/src/plugin_api/event.rs +++ b/zellij-utils/src/plugin_api/event.rs @@ -26,6 +26,7 @@ pub use super::generated_api::api::{ PluginConfigurationChangedPayload as ProtobufPluginConfigurationChangedPayload, PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession, SelectedText as ProtobufSelectedText, SessionManifest as ProtobufSessionManifest, + SoftKeyboardVisibilityChangedPayload as ProtobufSoftKeyboardVisibilityChangedPayload, SyntaxError as ProtobufSyntaxError, TabInfo as ProtobufTabInfo, TabMetadata as ProtobufTabMetadata, UserActionPayload as ProtobufUserActionPayload, WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing, @@ -588,6 +589,14 @@ impl TryFrom<ProtobufEvent> for Event { }, _ => Err("Malformed payload for HostTerminalThemeChanged Event"), }, + Some(ProtobufEventType::SoftKeyboardVisibilityChanged) => { + match protobuf_event.payload { + Some(ProtobufEventPayload::SoftKeyboardVisibilityChangedPayload(p)) => { + Ok(Event::SoftKeyboardVisibilityChanged(p.visible)) + }, + _ => Err("Malformed payload for SoftKeyboardVisibilityChanged Event"), + } + }, None => Err("Unknown Protobuf Event"), } } @@ -1129,6 +1138,15 @@ impl TryFrom<Event> for ProtobufEvent { payload: Some(event::Payload::HostTerminalThemeChangedPayload(payload)), }) }, + Event::SoftKeyboardVisibilityChanged(visible) => { + let payload = ProtobufSoftKeyboardVisibilityChangedPayload { visible }; + Ok(ProtobufEvent { + name: ProtobufEventType::SoftKeyboardVisibilityChanged as i32, + payload: Some(event::Payload::SoftKeyboardVisibilityChangedPayload( + payload, + )), + }) + }, Event::InitialKeybinds(keybinds) => { let mut protobuf_keybinds: Vec<ProtobufInputModeKeybinds> = vec![]; for (input_mode, input_mode_keybinds) in keybinds { @@ -1624,6 +1642,22 @@ impl TryFrom<MouseEventPayload> for Mouse { ), _ => Err("Malformed payload for mouse hover"), }, + Some(MouseEventName::MouseScrollLeft) => { + match mouse_event_payload.mouse_event_payload { + Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => { + Ok(Mouse::ScrollLeft(line_count as usize)) + }, + _ => Err("Malformed payload for mouse scroll left"), + } + }, + Some(MouseEventName::MouseScrollRight) => { + match mouse_event_payload.mouse_event_payload { + Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => { + Ok(Mouse::ScrollRight(line_count as usize)) + }, + _ => Err("Malformed payload for mouse scroll right"), + } + }, None => Err("Malformed payload for MouseEventName"), } } @@ -1690,6 +1724,18 @@ impl TryFrom<Mouse> for MouseEventPayload { }, )), }), + Mouse::ScrollLeft(cols) => Ok(MouseEventPayload { + mouse_event_name: MouseEventName::MouseScrollLeft as i32, + mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount( + cols as u32, + )), + }), + Mouse::ScrollRight(cols) => Ok(MouseEventPayload { + mouse_event_name: MouseEventName::MouseScrollRight as i32, + mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount( + cols as u32, + )), + }), } } } @@ -2078,6 +2124,9 @@ impl TryFrom<ProtobufEventType> for EventType { ProtobufEventType::HighlightClicked => EventType::HighlightClicked, ProtobufEventType::InitialKeybinds => EventType::InitialKeybinds, ProtobufEventType::HostTerminalThemeChanged => EventType::HostTerminalThemeChanged, + ProtobufEventType::SoftKeyboardVisibilityChanged => { + EventType::SoftKeyboardVisibilityChanged + }, }) } } @@ -2132,6 +2181,9 @@ impl TryFrom<EventType> for ProtobufEventType { EventType::HighlightClicked => ProtobufEventType::HighlightClicked, EventType::InitialKeybinds => ProtobufEventType::InitialKeybinds, EventType::HostTerminalThemeChanged => ProtobufEventType::HostTerminalThemeChanged, + EventType::SoftKeyboardVisibilityChanged => { + ProtobufEventType::SoftKeyboardVisibilityChanged + }, }) } } @@ -2986,12 +3038,16 @@ impl TryFrom<ProtobufPaneContents> for PaneContents { .selected_text .map(|st| st.try_into()) .transpose()?; + let cursor = protobuf_contents + .cursor + .map(|p| (p.column as usize, p.line as usize)); Ok(PaneContents { viewport: protobuf_contents.viewport, selected_text, lines_above_viewport: protobuf_contents.lines_above_viewport, lines_below_viewport: protobuf_contents.lines_below_viewport, + cursor, }) } } @@ -3003,12 +3059,17 @@ impl TryFrom<PaneContents> for ProtobufPaneContents { .selected_text .map(|st| st.try_into()) .transpose()?; + let cursor = pane_contents.cursor.map(|(x, y)| ProtobufPosition { + line: y as i64, + column: x as i64, + }); Ok(ProtobufPaneContents { viewport: pane_contents.viewport, selected_text, lines_above_viewport: pane_contents.lines_above_viewport, lines_below_viewport: pane_contents.lines_below_viewport, + cursor, }) } } @@ -3104,6 +3165,7 @@ fn serialize_pane_render_report_with_ansi_event_with_data() { selected_text: None, lines_above_viewport: vec![], lines_below_viewport: vec![], + cursor: None, }, ); let event = Event::PaneRenderReportWithAnsi(pane_contents_map); diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index 729159e3..c65bcbfd 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -207,6 +207,12 @@ enum CommandName { KillSessionsAndReply = 212; DeleteDeadSessionAndReply = 213; DeleteAllDeadSessionsAndReply = 214; + SetSoftKeyboard = 215; + SetTabFit = 216; + SetShadowFocus = 219; + NewTabUnfocused = 220; + NewTiledPaneInTab = 221; + ExitMobileMode = 222; } message PluginCommand { @@ -361,6 +367,11 @@ message PluginCommand { GetSessionListPayload get_session_list_payload = 161; KillSessionsPayload kill_sessions_and_reply_payload = 162; string delete_dead_session_and_reply_payload = 163; + SetSoftKeyboardPayload set_soft_keyboard_payload = 164; + SetTabFitPayload set_tab_fit_payload = 165; + PaneId set_shadow_focus_payload = 167; + NewTabUnfocusedPayload new_tab_unfocused_payload = 168; + NewTiledPaneInTabPayload new_tiled_pane_in_tab_payload = 169; } } @@ -369,6 +380,15 @@ message NewTabPayload { optional string cwd = 2; } +message NewTabUnfocusedPayload { + optional string name = 1; + optional string cwd = 2; +} + +message NewTiledPaneInTabPayload { + uint32 tab_position = 1; +} + message DumpSessionLayoutPayload { optional uint32 tab_index = 1; } @@ -1057,6 +1077,17 @@ message NewTabResponse { } } +message NewTabUnfocusedResponse { + oneof result { + uint64 tab_id = 1; + bool none = 2; + } +} + +message NewTiledPaneInTabResponse { + optional PaneId pane_id = 1; +} + message NewTabsResponse { repeated uint64 tab_ids = 1; // Only includes successfully created tabs } @@ -1328,3 +1359,18 @@ message DeleteDeadSessionResponse { message DeleteAllDeadSessionsResponse { optional string error = 1; // absent => success } + +message SetSoftKeyboardPayload { + bool on = 1; +} + +message Size { + uint32 rows = 1; + uint32 cols = 2; +} + +message SetTabFitPayload { + uint32 tab_id = 1; + PaneId pane_id = 2; + Size size = 3; +} diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index fa77739a..42b0774f 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -13,9 +13,9 @@ pub use super::generated_api::api::{ get_focused_pane_info_response, get_pane_cwd_response, get_pane_pid_response, get_pane_running_command_response, get_session_list_response, hide_floating_panes_response, highlight_style::Style as ProtobufHighlightStyleVariant, new_tab_response, - parse_layout_response, plugin_command::Payload, rename_layout_response, - save_layout_response, save_session_response, show_floating_panes_response, - BreakPanesToNewTabPayload, + new_tab_unfocused_response, parse_layout_response, plugin_command::Payload, + rename_layout_response, save_layout_response, save_session_response, + show_floating_panes_response, BreakPanesToNewTabPayload, BreakPanesToNewTabResponse as ProtobufBreakPanesToNewTabResponse, BreakPanesToTabWithIdPayload, BreakPanesToTabWithIdResponse as ProtobufBreakPanesToTabWithIdResponse, @@ -65,8 +65,10 @@ pub use super::generated_api::api::{ KillSessionsResponse as ProtobufKillSessionsResponse, ListTokensResponse, LoadNewPluginPayload, MessageToPluginPayload, MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload, NewPluginArgs as ProtobufNewPluginArgs, - NewTabPayload, NewTabResponse as ProtobufNewTabResponse, + NewTabPayload, NewTabResponse as ProtobufNewTabResponse, NewTabUnfocusedPayload, + NewTabUnfocusedResponse as ProtobufNewTabUnfocusedResponse, NewTabsResponse as ProtobufNewTabsResponse, NewTabsWithLayoutInfoPayload, + NewTiledPaneInTabPayload, NewTiledPaneInTabResponse as ProtobufNewTiledPaneInTabResponse, OpenCommandPaneBackgroundResponse as ProtobufOpenCommandPaneBackgroundResponse, OpenCommandPaneFloatingNearPluginPayload, OpenCommandPaneFloatingNearPluginResponse as ProtobufOpenCommandPaneFloatingNearPluginResponse, @@ -119,13 +121,15 @@ pub use super::generated_api::api::{ ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload, SessionListSnapshot as ProtobufSessionListSnapshot, SetFloatingPanePinnedPayload, SetPaneBorderlessPayload, SetPaneColorPayload, SetPaneRegexHighlightsPayload, - SetSelfMouseSelectionSupportPayload, SetTimeoutPayload, ShowCursorPayload, + SetSelfMouseSelectionSupportPayload, + SetSoftKeyboardPayload as ProtobufSetSoftKeyboardPayload, + SetTabFitPayload as ProtobufSetTabFitPayload, SetTimeoutPayload, ShowCursorPayload, ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload, ShowFloatingPanesResponse as ProtobufShowFloatingPanesResponse, ShowPaneWithIdPayload, - StackPanesPayload, SubscribePayload, SwitchSessionPayload, SwitchTabToIdPayload, - SwitchTabToPayload, TogglePaneBorderlessPayload, TogglePaneEmbedOrEjectForPaneIdPayload, - TogglePaneIdFullscreenPayload, UnsubscribePayload, WebRequestPayload, - WriteCharsToPaneIdPayload, WriteToPaneIdPayload, + Size as ProtobufSize, StackPanesPayload, SubscribePayload, SwitchSessionPayload, + SwitchTabToIdPayload, SwitchTabToPayload, TogglePaneBorderlessPayload, + TogglePaneEmbedOrEjectForPaneIdPayload, TogglePaneIdFullscreenPayload, UnsubscribePayload, + WebRequestPayload, WriteCharsToPaneIdPayload, WriteToPaneIdPayload, }, plugin_permission::PermissionType as ProtobufPermissionType, resize::ResizeAction as ProtobufResizeAction, @@ -141,11 +145,26 @@ use crate::data::{ }; use crate::input::actions::Action; use crate::input::layout::PercentOrFixed; +use crate::pane_size::Size; use std::collections::BTreeMap; use std::convert::TryFrom; use std::path::PathBuf; +fn size_from_protobuf(size: ProtobufSize) -> Size { + Size { + rows: size.rows as usize, + cols: size.cols as usize, + } +} + +fn size_to_protobuf(size: Size) -> ProtobufSize { + ProtobufSize { + rows: size.rows as u32, + cols: size.cols as u32, + } +} + impl Into<FloatingPaneCoordinates> for ProtobufFloatingPaneCoordinates { fn into(self) -> FloatingPaneCoordinates { FloatingPaneCoordinates { @@ -900,6 +919,27 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { }), _ => Err("Mismatched payload for NewTab"), }, + Some(CommandName::NewTabUnfocused) => match protobuf_plugin_command.payload { + Some(Payload::NewTabUnfocusedPayload(payload)) => { + Ok(PluginCommand::NewTabUnfocused { + name: payload.name, + cwd: payload.cwd, + }) + }, + None => Ok(PluginCommand::NewTabUnfocused { + name: None, + cwd: None, + }), + _ => Err("Mismatched payload for NewTabUnfocused"), + }, + Some(CommandName::NewTiledPaneInTab) => match protobuf_plugin_command.payload { + Some(Payload::NewTiledPaneInTabPayload(payload)) => { + Ok(PluginCommand::NewTiledPaneInTab { + tab_position: payload.tab_position as usize, + }) + }, + _ => Err("Mismatched payload for NewTiledPaneInTab"), + }, Some(CommandName::GoToNextTab) => { if protobuf_plugin_command.payload.is_some() { return Err("GoToNextTab should not have a payload"); @@ -1448,6 +1488,38 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { Some(CommandName::DeleteAllDeadSessionsAndReply) => { Ok(PluginCommand::DeleteAllDeadSessionsAndReply) }, + Some(CommandName::SetSoftKeyboard) => match protobuf_plugin_command.payload { + Some(Payload::SetSoftKeyboardPayload(payload)) => { + Ok(PluginCommand::SetSoftKeyboard(payload.on)) + }, + _ => Err("Mismatched payload for SetSoftKeyboard"), + }, + Some(CommandName::SetTabFit) => match protobuf_plugin_command.payload { + Some(Payload::SetTabFitPayload(payload)) => { + let fit = match (payload.pane_id, payload.size) { + (Some(pane_id), Some(size)) => { + Some((pane_id.try_into()?, size_from_protobuf(size))) + }, + (None, None) => None, + _ => return Err("Malformed set_tab_fit_payload payload"), + }; + Ok(PluginCommand::SetTabFit { + tab_id: payload.tab_id as usize, + fit, + }) + }, + _ => Err("Mismatched payload for SetTabFit"), + }, + Some(CommandName::ExitMobileMode) => match protobuf_plugin_command.payload { + Some(_) => Err("ExitMobileMode should have no payload, found a payload"), + None => Ok(PluginCommand::ExitMobileMode), + }, + Some(CommandName::SetShadowFocus) => match protobuf_plugin_command.payload { + Some(Payload::SetShadowFocusPayload(pane_id)) => { + Ok(PluginCommand::SetShadowFocus(pane_id.try_into()?)) + }, + _ => Err("Mismatched payload for SetShadowFocus"), + }, Some(CommandName::DumpSessionLayout) => match protobuf_plugin_command.payload { Some(Payload::DumpSessionLayoutPayload(payload)) => { Ok(PluginCommand::DumpSessionLayout { @@ -2890,6 +2962,21 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::NewTab as i32, payload: Some(Payload::NewTabPayload(NewTabPayload { name, cwd })), }), + PluginCommand::NewTabUnfocused { name, cwd } => Ok(ProtobufPluginCommand { + name: CommandName::NewTabUnfocused as i32, + payload: Some(Payload::NewTabUnfocusedPayload(NewTabUnfocusedPayload { + name, + cwd, + })), + }), + PluginCommand::NewTiledPaneInTab { tab_position } => Ok(ProtobufPluginCommand { + name: CommandName::NewTiledPaneInTab as i32, + payload: Some(Payload::NewTiledPaneInTabPayload( + NewTiledPaneInTabPayload { + tab_position: tab_position as u32, + }, + )), + }), PluginCommand::GoToNextTab => Ok(ProtobufPluginCommand { name: CommandName::GoToNextTab as i32, payload: None, @@ -3315,6 +3402,32 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::DeleteAllDeadSessionsAndReply as i32, payload: None, }), + PluginCommand::SetSoftKeyboard(on) => Ok(ProtobufPluginCommand { + name: CommandName::SetSoftKeyboard as i32, + payload: Some(Payload::SetSoftKeyboardPayload( + ProtobufSetSoftKeyboardPayload { on }, + )), + }), + PluginCommand::SetTabFit { tab_id, fit } => { + let (pane_id, size) = match fit { + Some((pane_id, size)) => { + (Some(pane_id.try_into()?), Some(size_to_protobuf(size))) + }, + None => (None, None), + }; + Ok(ProtobufPluginCommand { + name: CommandName::SetTabFit as i32, + payload: Some(Payload::SetTabFitPayload(ProtobufSetTabFitPayload { + tab_id: tab_id as u32, + pane_id, + size, + })), + }) + }, + PluginCommand::ExitMobileMode => Ok(ProtobufPluginCommand { + name: CommandName::ExitMobileMode as i32, + payload: None, + }), PluginCommand::DumpSessionLayout { tab_index } => Ok(ProtobufPluginCommand { name: CommandName::DumpSessionLayout as i32, payload: tab_index.map(|idx| { @@ -3437,6 +3550,10 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::SendSigintToPaneId as i32, payload: Some(Payload::SendSigintToPaneIdPayload(pane_id.try_into()?)), }), + PluginCommand::SetShadowFocus(pane_id) => Ok(ProtobufPluginCommand { + name: CommandName::SetShadowFocus as i32, + payload: Some(Payload::SetShadowFocusPayload(pane_id.try_into()?)), + }), PluginCommand::SendSigkillToPaneId(pane_id) => Ok(ProtobufPluginCommand { name: CommandName::SendSigkillToPaneId as i32, payload: Some(Payload::SendSigkillToPaneIdPayload(pane_id.try_into()?)), @@ -4433,7 +4550,8 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { // Conversion implementations for tab creation response types use crate::data::{ BreakPanesToNewTabResponse, BreakPanesToTabWithIdResponse, BreakPanesToTabWithIndexResponse, - FocusOrCreateTabResponse, NewTabResponse, NewTabsResponse, OpenCommandPaneBackgroundResponse, + FocusOrCreateTabResponse, NewTabResponse, NewTabUnfocusedResponse, NewTabsResponse, + NewTiledPaneInTabResponse, OpenCommandPaneBackgroundResponse, OpenCommandPaneFloatingNearPluginResponse, OpenCommandPaneFloatingResponse, OpenCommandPaneInPlaceOfPaneIdResponse, OpenCommandPaneInPlaceOfPluginResponse, OpenCommandPaneInPlaceResponse, OpenCommandPaneNearPluginResponse, OpenCommandPaneResponse, @@ -4468,6 +4586,47 @@ impl From<NewTabResponse> for ProtobufNewTabResponse { } } +impl TryFrom<ProtobufNewTabUnfocusedResponse> for NewTabUnfocusedResponse { + type Error = &'static str; + fn try_from(protobuf: ProtobufNewTabUnfocusedResponse) -> Result<Self, Self::Error> { + match protobuf.result { + Some(new_tab_unfocused_response::Result::TabId(id)) => Ok(Some(id as usize)), + Some(new_tab_unfocused_response::Result::None(_)) | None => Ok(None), + } + } +} + +impl From<NewTabUnfocusedResponse> for ProtobufNewTabUnfocusedResponse { + fn from(response: NewTabUnfocusedResponse) -> Self { + match response { + Some(tab_id) => ProtobufNewTabUnfocusedResponse { + result: Some(new_tab_unfocused_response::Result::TabId(tab_id as u64)), + }, + None => ProtobufNewTabUnfocusedResponse { + result: Some(new_tab_unfocused_response::Result::None(true)), + }, + } + } +} + +impl TryFrom<ProtobufNewTiledPaneInTabResponse> for NewTiledPaneInTabResponse { + type Error = &'static str; + fn try_from(protobuf: ProtobufNewTiledPaneInTabResponse) -> Result<Self, Self::Error> { + match protobuf.pane_id { + Some(pane_id) => Ok(Some(pane_id.try_into()?)), + None => Ok(None), + } + } +} + +impl From<NewTiledPaneInTabResponse> for ProtobufNewTiledPaneInTabResponse { + fn from(response: NewTiledPaneInTabResponse) -> Self { + ProtobufNewTiledPaneInTabResponse { + pane_id: response.map(|p| p.try_into().unwrap()), + } + } +} + impl TryFrom<ProtobufNewTabsResponse> for NewTabsResponse { type Error = &'static str; fn try_from(protobuf: ProtobufNewTabsResponse) -> Result<Self, Self::Error> { @@ -5053,3 +5212,47 @@ impl From<OpenPluginPaneFloatingResponse> for ProtobufOpenPluginPaneFloatingResp } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::{PaneId, PluginCommand}; + use crate::pane_size::Size; + + #[test] + fn set_tab_fit_set_protobuf_round_trip() { + let original = PluginCommand::SetTabFit { + tab_id: 7, + fit: Some((PaneId::Terminal(3), Size { rows: 24, cols: 80 })), + }; + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::SetTabFit { tab_id, fit } => { + assert_eq!(tab_id, 7); + assert_eq!( + fit, + Some((PaneId::Terminal(3), Size { rows: 24, cols: 80 })) + ); + }, + other => panic!("expected SetTabFit, got {:?}", other), + } + } + + #[test] + fn set_tab_fit_clear_protobuf_round_trip() { + let original = PluginCommand::SetTabFit { + tab_id: 7, + fit: None, + }; + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::SetTabFit { tab_id, fit } => { + assert_eq!(tab_id, 7); + assert_eq!(fit, None); + }, + other => panic!("expected SetTabFit, got {:?}", other), + } + } +} |
