public Task ResizeTerminalAsync(byte id, TerminalSize size) { return(_appServiceConnection.SendMessageAsync(CreateMessage(new ResizeTerminalRequest { TerminalId = id, NewSize = size }))); }
public void Start(CreateTerminalRequest request, TerminalsManager terminalsManager) { Id = request.Id; _terminalsManager = terminalsManager; _terminalSize = request.Size; ShellExecutableName = Path.GetFileNameWithoutExtension(request.Profile.Location); var cwd = GetWorkingDirectory(request.Profile); var args = string.Empty; if (!string.IsNullOrWhiteSpace(request.Profile.Location)) { args = $"\"{request.Profile.Location}\" {request.Profile.Arguments}"; } else { args = request.Profile.Arguments; } _terminal = new Terminal(); _terminal.OutputReady += _terminal_OutputReady; _terminal.Exited += _terminal_Exited; Task.Run(() => _terminal.Start(args, cwd, terminalsManager.GetDefaultEnvironmentVariableString(request.Profile.EnvironmentVariables), request.Size.Columns, request.Size.Rows)); }
public Task ResizeTerminal(int id, TerminalSize size) { var request = new ResizeTerminalRequest { TerminalId = id, NewSize = size }; return(_appServiceConnection.SendMessageAsync(CreateMessage(request))); }
public WinPty(Profile profile, TerminalSize size, bool separateStdErr = false) { _size = size; IntPtr err = IntPtr.Zero; IntPtr cfg = IntPtr.Zero; IntPtr spawnCfg = IntPtr.Zero; try { ulong cfgFlags = WINPTY_FLAG_COLOR_ESCAPES; if (separateStdErr) { cfgFlags |= WINPTY_FLAG_CONERR; } cfg = winpty_config_new(cfgFlags, out err); winpty_config_set_initial_size(cfg, size.Columns, size.Rows); _handle = winpty_open(cfg, out err); if (err != IntPtr.Zero) { throw new WinPtrException(err); } string cmdline = null; string env = GetEnvironmentString(profile.EnvironmentVariables); if (profile.Arguments != null && profile.Arguments.Length > 0) { cmdline = string.Join(" ", profile.Arguments.Select(x => $"\"{x}\"")); } spawnCfg = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, profile.Command, cmdline, profile.CurrentWorkingDirectory, env, out err); if (err != IntPtr.Zero) { throw new WinPtrException(err); } StandardInput = CreatePipe(winpty_conin_name(_handle), PipeDirection.Out); StandardOutput = CreatePipe(winpty_conout_name(_handle), PipeDirection.In); if (separateStdErr) { StandardError = CreatePipe(winpty_conerr_name(_handle), PipeDirection.In); } if (!winpty_spawn(_handle, spawnCfg, out IntPtr process, out IntPtr thread, out int procError, out err)) { throw new WinPtrException(err); } } finally { winpty_config_free(cfg); winpty_spawn_config_free(spawnCfg); winpty_error_free(err); } }
public void ResizeTerminal(int id, TerminalSize size) { if (_terminals.TryGetValue(id, out TerminalSession terminal)) { terminal.Resize(size); } else { Debug.WriteLine($"ResizeTerminal: terminal with id '{id}' was not found"); } }
private Size GetWindowSizeForBufferSize(TerminalSize size) { Size charSize = terminalControl.CharSize; Size snappedConsoleSize = new Size(size.Columns * charSize.Width, size.Rows * charSize.Height); Size result = new Size(Math.Ceiling(snappedConsoleSize.Width + _consoleSizeDelta.Width) + 2, Math.Ceiling(snappedConsoleSize.Height + _consoleSizeDelta.Height)); return(result); }
/// <summary> /// to be called by view when ready /// </summary> /// <param name="shellProfile"></param> /// <param name="size"></param> /// <param name="sessionType"></param> public async Task StartShellProcess(ShellProfile shellProfile, TerminalSize size, SessionType sessionType) { _trayProcessCommunicationService.SubscribeForTerminalOutput(Id, t => OutputReceived?.Invoke(this, t)); var response = await _trayProcessCommunicationService.CreateTerminal(Id, size, shellProfile, sessionType).ConfigureAwait(true); if (response.Success) { FallbackTitle = response.ShellExecutableName; SetTitle(FallbackTitle); } }
public void ResizeTerminal(byte id, TerminalSize size) { if (_terminals.TryGetValue(id, out TerminalSessionInfo sessionInfo)) { sessionInfo.Session.Resize(size); } else { Debug.WriteLine($"ResizeTerminal: terminal with id '{id}' was not found"); } }
public async Task <CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellProfile shellProfile) { var request = new CreateTerminalRequest { Size = size, Profile = shellProfile }; var responseMessage = await _appServiceConnection.SendMessageAsync(CreateMessage(request)); return(JsonConvert.DeserializeObject <CreateTerminalResponse>(responseMessage[MessageKeys.Content])); }
public NativePty(ExecutionProfile executionProfile, TerminalSize size) { SafeFileHandle stdin; SafeFileHandle stdout; CreatePipe(out stdin, out _writeHandle, IntPtr.Zero, 0); CreatePipe(out _readHandle, out stdout, IntPtr.Zero, 0); W32Throw(CreatePseudoConsole(new COORD { X = (short)size.Columns, Y = (short)size.Rows }, stdin, stdout, 0, out this._ptyHandle)); var allocSize = IntPtr.Zero; InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref allocSize); if (allocSize == IntPtr.Zero) { W32Throw(0, "allocation granularity whatever."); } var startupInfo = new STARTUPINFOEX { StartupInfo = { cb = Marshal.SizeOf <STARTUPINFOEX>() }, lpAttributeList = Marshal.AllocHGlobal(allocSize) }; W32Throw(InitializeProcThreadAttributeList(startupInfo.lpAttributeList, 1, 0, ref allocSize)); W32Throw(UpdateProcThreadAttribute(startupInfo.lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, _ptyHandle, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero)); var processSecurityAttr = new SECURITY_ATTRIBUTES(); var threadSecurityAttr = new SECURITY_ATTRIBUTES(); processSecurityAttr.nLength = threadSecurityAttr.nLength = Marshal.SizeOf <SECURITY_ATTRIBUTES>(); var args = executionProfile.Arguments ?? Array.Empty <string>(); var cmdline = executionProfile.EscapeArguments ? string.Join(" ", args.Select(x => $"\"{x}\"")) : string.Join(" ", args); W32Throw(CreateProcess(executionProfile.Command, cmdline, ref processSecurityAttr, ref threadSecurityAttr, false, EXTENDED_STARTUPINFO_PRESENT, IntPtr.Zero, null, ref startupInfo, out var processInfo)); DeleteProcThreadAttributeList(startupInfo.lpAttributeList); Marshal.FreeHGlobal(startupInfo.lpAttributeList); StandardOutput = new FileStream(_readHandle, FileAccess.Read); StandardInput = new FileStream(_writeHandle, FileAccess.Write); }
private async Task ResizeTask() { while (true) { TimeSpan delay; TerminalSize size = null; lock (_resizeLock) { if (_requestedSize?.EquivalentTo(_setSize) ?? true) { // Resize finished. Unblock output and exit. if (_outputBlockedBuffer != null) { OnOutput?.Invoke(this, _outputBlockedBuffer.ToArray()); _outputBlockedBuffer.Dispose(); _outputBlockedBuffer = null; } _resizeTask = null; break; } delay = _resizeScheduleTime.Subtract(DateTime.UtcNow); // To avoid sleeping for only few milliseconds we're introducing a threshold of 10 milliseconds if (delay.TotalMilliseconds < 10) { _setSize = size = _requestedSize; if (_outputBlockedBuffer == null) { _outputBlockedBuffer = new MemoryStream(); } } } if (size == null) { await Task.Delay(delay).ConfigureAwait(false); } else { await ViewModel.Terminal.SetSizeAsync(_requestedSize).ConfigureAwait(false); } } }
// Must be called from a code locked with _resizeLock private void ScheduleResize(TerminalSize size, bool scheduleIfEqual) { if (!scheduleIfEqual && size.EquivalentTo(_requestedSize)) { return; } _requestedSize = size; _resizeScheduleTime = DateTime.UtcNow.Add(ResizeDelay); if (_resizeTask == null) { _resizeTask = ResizeTask(); } }
public Task ResizeTerminal(int id, TerminalSize size) { var request = new ResizeTerminalRequest { TerminalId = id, NewSize = size }; var message = new ValueSet { { MessageKeys.Type, MessageTypes.ResizeTerminalRequest }, { MessageKeys.Content, JsonConvert.SerializeObject(request) } }; return(_appServiceConnection.SendMessageAsync(message).AsTask()); }
public void Resize(TerminalSize size) { var errorHandle = IntPtr.Zero; try { winpty_set_size(_handle, size.Columns, size.Rows, out errorHandle); if (errorHandle != IntPtr.Zero) { throw new Exception(winpty_error_msg(errorHandle).ToString()); } } finally { winpty_error_free(errorHandle); } }
public async Task <CreateTerminalResponse> CreateTerminal(TerminalSize size, ShellProfile shellProfile) { var request = new CreateTerminalRequest { Size = size, Profile = shellProfile }; var message = new ValueSet { { MessageKeys.Type, MessageTypes.CreateTerminalRequest }, { MessageKeys.Content, JsonConvert.SerializeObject(request) } }; var responseMessage = await _appServiceConnection.SendMessageAsync(message); return(JsonConvert.DeserializeObject <CreateTerminalResponse>((string)responseMessage.Message[MessageKeys.Content])); }
public void ResizeTerminal(byte id, TerminalSize size) { if (_terminals.TryGetValue(id, out TerminalSessionInfo sessionInfo)) { try { sessionInfo.Session.Resize(size); } catch (Exception e) { Logger.Instance.Error($"ResizeTerminal: resizing of terminal with id '{id}' failed with exception: {e}"); } } else { Debug.WriteLine($"ResizeTerminal: terminal with id '{id}' was not found"); } }
public async Task <CreateTerminalResponse> CreateTerminalAsync(byte id, TerminalSize size, ShellProfile shellProfile, SessionType sessionType) { var request = new CreateTerminalRequest { Id = id, Size = size, Profile = shellProfile, SessionType = sessionType }; Logger.Instance.Debug("Sending CreateTerminalRequest: {@request}", request); var response = await GetResponseAsync <CreateTerminalResponse>(request).ConfigureAwait(false); Logger.Instance.Debug("Received CreateTerminalResponse: {@response}", response); return(response); }
private async Task <bool> StartShellProcessAsync(TerminalSize size) { var sessionType = ViewModel.ShellProfile.UseConPty && ViewModel.ApplicationView.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7) ? SessionType.ConPty : SessionType.WinPty; var response = await ViewModel.Terminal.StartShellProcessAsync(ViewModel.ShellProfile, size, sessionType, ViewModel.XtermBufferState).ConfigureAwait(false); if (!response.Success) { await Dispatcher.ExecuteAsync(async() => await ViewModel.DialogService.ShowMessageDialogAsync("Error", response.Error, DialogButton.OK)) .ConfigureAwait(false); ViewModel.Terminal.ReportLauchFailed(); return(false); } return(true); }
public async Task <CreateTerminalResponse> CreateTerminal(byte id, TerminalSize size, ShellProfile shellProfile, SessionType sessionType) { var request = new CreateTerminalRequest { Id = id, Size = size, Profile = shellProfile, SessionType = sessionType }; Logger.Instance.Debug("Sending CreateTerminalRequest: {@request}", request); var responseMessage = await _appServiceConnection.SendMessageAsync(CreateMessage(request)); var response = JsonConvert.DeserializeObject <CreateTerminalResponse>((string)responseMessage[MessageKeys.Content]); Logger.Instance.Debug("Received CreateTerminalResponse: {@response}", response); return(response); }
protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); var config = _configService.Config; int columns = Math.Max(config.Columns, MinColumns); int rows = Math.Max(config.Rows, MinRows); _terminalSize = new TerminalSize(columns, rows); FixWindowSize(); Profile profile = config.Profile; if (profile == null) { profile = DefaultProfile.Get(); } _defaultProfile = ExpandVariables(profile); CreateSession(_defaultProfile); }
void IxtermEventListener.OnTerminalResized(int columns, int rows) { if (_terminalClosed) { return; } var size = new TerminalSize { Columns = columns, Rows = rows }; lock (_resizeLock) { if (_setSize == null) { // Initialization not finished yet _requestedSize = size; } else { ScheduleResize(size, false); } } }
private void SetTermialSize(TerminalSize size) { if (_terminalSize != size) { _terminalSize = size; if (_currentSession != null) { _currentSession.Size = size; } if (Ready) { // Save configuration _configService.Config.Columns = size.Columns; _configService.Config.Rows = size.Rows; _configService.Save(); // Update hint overlay resizeHint.Hint = size; resizeHint.IsShowing = true; resizeHint.IsShowing = IsResizing; } } }
/// <summary> /// To be called by view /// </summary> public async Task SetSizeAsync(TerminalSize size) { await _trayProcessCommunicationService.ResizeTerminalAsync(Id, size).ConfigureAwait(false); SizeChanged?.Invoke(this, size); }
public async Task InitializeAsync(TerminalViewModel viewModel) { ViewModel = viewModel; ViewModel.Terminal.OutputReceived += Terminal_OutputReceived; ViewModel.Terminal.RegisterSelectedTextCallback(() => ExecuteScriptAsync("term.getSelection()")); ViewModel.Terminal.Closed += Terminal_Closed; _webView.SetBinding(ContextFlyoutProperty, new Binding { Converter = (IValueConverter)Application.Current.Resources["MenuViewModelToFlyoutMenuConverter"], Mode = BindingMode.OneWay, Source = ViewModel, Path = new PropertyPath(nameof(TerminalViewModel.ContextMenu)) }); var options = ViewModel.SettingsService.GetTerminalOptions(); var keyBindings = ViewModel.SettingsService.GetCommandKeyBindings(); var profiles = ViewModel.SettingsService.GetShellProfiles(); var sshprofiles = ViewModel.SettingsService.GetSshProfiles(); var theme = ViewModel.TerminalTheme; // Waiting for WebView.NavigationCompleted event to happen await _tcsNavigationCompleted.Task.ConfigureAwait(false); var size = await CreateXtermViewAsync(options, theme.Colors, FlattenKeyBindings(keyBindings, profiles, sshprofiles)).ConfigureAwait(false); // Waiting for IxtermEventListener.OnInitialized() call to happen await _tcsConnected.Task; lock (_resizeLock) { // Check to see if some resizing has happened meanwhile if (_requestedSize != null) { size = _requestedSize; } else { _requestedSize = size; } } if (false == await StartShellProcessAsync(size).ConfigureAwait(false)) { return; } lock (_resizeLock) { // Check to see if some resizing has happened meanwhile if (!size.EquivalentTo(_requestedSize)) { ScheduleResize(_requestedSize, true); } else { _setSize = size; } } if (ViewModel.ShellProfile?.Tag is ISessionSuccessTracker tracker) { tracker.SetSuccessfulSessionStart(); } await Dispatcher.ExecuteAsync(() => _webView.Focus(FocusState.Programmatic)).ConfigureAwait(false); }
public void Resize(TerminalSize size) { _terminal.Resize(size.Columns, size.Rows); }
public bool EquivalentTo(TerminalSize other) => ReferenceEquals(this, other) || other != null && Columns.Equals(other.Columns) && Rows.Equals(other.Rows);
/// <summary> /// To be called by view when ready /// </summary> public async Task <TerminalResponse> StartShellProcessAsync(ShellProfile shellProfile, TerminalSize size, SessionType sessionType, string termState) { if (!_requireShellProcessStart && !string.IsNullOrEmpty(termState)) { OutputReceived?.Invoke(this, Encoding.UTF8.GetBytes(termState)); } _trayProcessCommunicationService.SubscribeForTerminalOutput(Id, t => OutputReceived?.Invoke(this, t)); if (_requireShellProcessStart) { var response = await _trayProcessCommunicationService .CreateTerminalAsync(Id, size, shellProfile, sessionType).ConfigureAwait(false); if (response.Success) { _fallbackTitle = response.Name; SetTitle(_fallbackTitle); } return(response); } else { return(await _trayProcessCommunicationService.PauseTerminalOutputAsync(Id, false)); } }
internal TerminalResizeEventArgs(TerminalSize size) { Size = size; }
public void Start(CreateTerminalRequest request, TerminalsManager terminalsManager) { Id = request.Id; _terminalsManager = terminalsManager; _terminalSize = request.Size; var configHandle = IntPtr.Zero; var spawnConfigHandle = IntPtr.Zero; var errorHandle = IntPtr.Zero; try { configHandle = winpty_config_new(WINPTY_FLAG_COLOR_ESCAPES, out errorHandle); winpty_config_set_initial_size(configHandle, request.Size.Columns, request.Size.Rows); _handle = winpty_open(configHandle, out errorHandle); if (errorHandle != IntPtr.Zero) { throw new Exception(winpty_error_msg(errorHandle)); } var cwd = GetWorkingDirectory(request.Profile); var args = request.Profile.Arguments; if (!string.IsNullOrWhiteSpace(request.Profile.Location)) { args = $"\"{request.Profile.Location}\" {args}"; } spawnConfigHandle = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, request.Profile.Location, args, cwd, terminalsManager.GetDefaultEnvironmentVariableString(request.Profile.EnvironmentVariables), out errorHandle); if (errorHandle != IntPtr.Zero) { throw new Exception(winpty_error_msg(errorHandle)); } _stdin = CreatePipe(winpty_conin_name(_handle), PipeDirection.Out); _stdout = CreatePipe(winpty_conout_name(_handle), PipeDirection.In); if (!winpty_spawn(_handle, spawnConfigHandle, out IntPtr process, out IntPtr thread, out int procError, out errorHandle)) { throw new Exception($@"Failed to start the shell process. Please check your shell settings.{Environment.NewLine}Tried to start: {request.Profile.Location} ""{request.Profile.Arguments}"""); } var shellProcessId = ProcessApi.GetProcessId(process); _shellProcess = Process.GetProcessById(shellProcessId); _shellProcess.EnableRaisingEvents = true; _shellProcess.Exited += _shellProcess_Exited; if (!string.IsNullOrWhiteSpace(request.Profile.Location)) { ShellExecutableName = Path.GetFileNameWithoutExtension(request.Profile.Location); } else { ShellExecutableName = request.Profile.Arguments.Split(' ')[0]; } } finally { winpty_config_free(configHandle); winpty_spawn_config_free(spawnConfigHandle); winpty_error_free(errorHandle); } ListenToStdOut(); }
/// <summary> /// To be called by view /// </summary> public async Task SetSize(TerminalSize size) { await _trayProcessCommunicationService.ResizeTerminal(Id, size); SizeChanged?.Invoke(this, size); }