From 44074accc7eb2fe0659ccd5166975d54dfb5cc68 Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Tue, 14 Mar 2023 09:09:55 +0100 Subject: [PATCH] Terminal: Use QtcProcess to start terminal window Previously DesktopDevice::openTerminal used custom code to open a terminal window. This patch changes it to use QtcProcess with TerminalMode::On. This also removes the need for "openTerminal.py" on macOS. Change-Id: Iec978bdd19487ff8e59dcd88c35c2d01b0681022 Reviewed-by: Cristian Adam --- share/qtcreator/CMakeLists.txt | 4 - share/qtcreator/scripts/openTerminal.py | 112 ------------------ src/libs/utils/launcherpackets.cpp | 6 +- src/libs/utils/launcherpackets.h | 1 + src/libs/utils/launchersocket.cpp | 1 + src/libs/utils/processinterface.h | 1 + src/libs/utils/processutils.cpp | 33 ++++-- src/libs/utils/processutils.h | 2 +- src/libs/utils/qtcprocess.cpp | 15 ++- src/libs/utils/qtcprocess.h | 3 + src/libs/utils/terminalcommand.cpp | 8 +- src/libs/utils/terminalhooks.cpp | 19 +-- src/libs/utils/terminalinterface.cpp | 4 +- src/plugins/docker/dockerdevice.cpp | 11 +- .../devicesupport/desktopdevice.cpp | 74 +++--------- .../devicesupport/desktopdevice.h | 8 +- src/plugins/remotelinux/linuxdevice.cpp | 2 + src/plugins/terminal/terminalpane.cpp | 9 +- .../processlauncher/launchersockethandler.cpp | 5 +- 19 files changed, 102 insertions(+), 216 deletions(-) delete mode 100755 share/qtcreator/scripts/openTerminal.py diff --git a/share/qtcreator/CMakeLists.txt b/share/qtcreator/CMakeLists.txt index 0a868915a3d..49b556b5c52 100644 --- a/share/qtcreator/CMakeLists.txt +++ b/share/qtcreator/CMakeLists.txt @@ -37,10 +37,6 @@ set(resource_files debugger/utils.py ) -if (APPLE) - set(resource_directories ${resource_directories} scripts) -endif() - # copy resource directories during build qtc_copy_to_builddir(copy_share_to_builddir DIRECTORIES ${resource_directories} diff --git a/share/qtcreator/scripts/openTerminal.py b/share/qtcreator/scripts/openTerminal.py deleted file mode 100755 index 3dd1bcb1b92..00000000000 --- a/share/qtcreator/scripts/openTerminal.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) 2018 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -import os -import pipes -import stat -import subprocess -import sys -from tempfile import NamedTemporaryFile - -def quote_shell(arg): - return pipes.quote(arg) - -def clean_environment_script(): - # keep some basic environment settings to ensure functioning terminal and config files - env_to_keep = ' '.join(['_', 'HOME', 'LOGNAME', 'PWD', 'SHELL', 'TMPDIR', 'USER', 'TERM', - 'TERM_PROGRAM', 'TERM_PROGRAM_VERSION', 'TERM_SESSION_CLASS_ID', - 'TERM_SESSION_ID']) - return r''' -function ignore() { - local keys=(''' + env_to_keep + ''') - local v=$1 - for e in "${keys[@]}"; do [[ "$e" == "$v" ]] && return 0; done -} -while read -r line; do - key=$(echo $line | /usr/bin/cut -d '=' -f 1) - ignore $key || unset $key -done < <(env) -''' - -def system_login_script_bash(): - return r''' -[ -r /etc/profile ] && source /etc/profile -# fake behavior of /etc/profile as if BASH was set. It isn't for non-interactive shell -export PS1='\h:\W \u\$ ' -[ -r /etc/bashrc ] && source /etc/bashrc -''' - -def login_script_bash(): - return r''' -if [ -f $HOME/.bash_profile ]; then - source $HOME/.bash_profile -elif [ -f $HOME/.bash_login ]; then - source $HOME/.bash_login ] -elif [ -f $HOME/.profile ]; then - source $HOME/.profile -fi -''' - -def system_login_script_zsh(): - return '[ -r /etc/profile ] && source /etc/profile\n' - -def login_script_zsh(): - return r''' -[ -r $HOME/.zprofile ] && source $HOME/.zprofile -[ -r $HOME/.zshrc ] && source $HOME/.zshrc -[ -r $HOME/.zlogin ] && source $HOME/.zlogin -''' - -def environment_script(): - return ''.join(['export ' + quote_shell(key + '=' + os.environ[key]) + '\n' - for key in os.environ]) - -def zsh_setup(shell): - return (shell, - system_login_script_zsh, - login_script_zsh, - shell + ' -c', - shell + ' -d -f') - -def bash_setup(shell): - bash = shell if shell is not None and shell.endswith('/bash') else '/bin/bash' - return (bash, - system_login_script_bash, - login_script_bash, - bash + ' -c', - bash + ' --noprofile -l') - -def main(): - # create temporary file to be sourced into bash that deletes itself - with NamedTemporaryFile(mode='wt', delete=False) as shell_script: - shell = os.environ.get('SHELL') - shell, system_login_script, login_script, non_interactive_shell, interactive_shell = ( - zsh_setup(shell) if shell is not None and shell.endswith('/zsh') - else bash_setup(shell)) - - commands = ('#!' + shell + '\n' + - 'rm ' + quote_shell(shell_script.name) + '\n' + - clean_environment_script() + - system_login_script() + # /etc/(z)profile by default resets the path, so do first - environment_script() + - login_script() + - 'cd ' + quote_shell(os.getcwd()) + '\n' + - ('exec ' + non_interactive_shell + ' ' + - quote_shell(' '.join([quote_shell(arg) for arg in sys.argv[1:]])) + '\n' - if len(sys.argv) > 1 else 'exec ' + interactive_shell + '\n') - ) - shell_script.write(commands) - shell_script.flush() - os.chmod(shell_script.name, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) - # TODO /usr/bin/open doesn't work with notarized app in macOS 13, - # use osascript instead (QTCREATORBUG-28683). - # This has the disadvantage that the Terminal windows doesn't close - # automatically anymore. - # subprocess.call(['/usr/bin/open', '-a', 'Terminal', shell_script.name]) - subprocess.call(['/usr/bin/osascript', '-e', 'tell app "Terminal" to activate']) - subprocess.call(['/usr/bin/osascript', '-e', 'tell app "Terminal" to do script "' + shell_script.name + '"']) - -if __name__ == "__main__": - main() diff --git a/src/libs/utils/launcherpackets.cpp b/src/libs/utils/launcherpackets.cpp index 13c3a1560d4..37261224ef5 100644 --- a/src/libs/utils/launcherpackets.cpp +++ b/src/libs/utils/launcherpackets.cpp @@ -48,7 +48,8 @@ void StartProcessPacket::doSerialize(QDataStream &stream) const << lowPriority << unixTerminalDisabled << useCtrlCStub - << reaperTimeout; + << reaperTimeout + << createConsoleOnWindows; } void StartProcessPacket::doDeserialize(QDataStream &stream) @@ -68,7 +69,8 @@ void StartProcessPacket::doDeserialize(QDataStream &stream) >> lowPriority >> unixTerminalDisabled >> useCtrlCStub - >> reaperTimeout; + >> reaperTimeout + >> createConsoleOnWindows; processMode = Utils::ProcessMode(processModeInt); processChannelMode = QProcess::ProcessChannelMode(processChannelModeInt); } diff --git a/src/libs/utils/launcherpackets.h b/src/libs/utils/launcherpackets.h index 2f0bae2915e..27e98a74e5b 100644 --- a/src/libs/utils/launcherpackets.h +++ b/src/libs/utils/launcherpackets.h @@ -98,6 +98,7 @@ public: bool unixTerminalDisabled = false; bool useCtrlCStub = false; int reaperTimeout = 500; + bool createConsoleOnWindows = false; private: void doSerialize(QDataStream &stream) const override; diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp index 07ebc84df9a..f4feda595a4 100644 --- a/src/libs/utils/launchersocket.cpp +++ b/src/libs/utils/launchersocket.cpp @@ -257,6 +257,7 @@ void CallerHandle::start(const QString &program, const QStringList &arguments) p.unixTerminalDisabled = m_setup->m_unixTerminalDisabled; p.useCtrlCStub = m_setup->m_useCtrlCStub; p.reaperTimeout = m_setup->m_reaperTimeout; + p.createConsoleOnWindows = m_setup->m_createConsoleOnWindows; sendPacket(p); } diff --git a/src/libs/utils/processinterface.h b/src/libs/utils/processinterface.h index 5f3a4378d48..bd02428ef9b 100644 --- a/src/libs/utils/processinterface.h +++ b/src/libs/utils/processinterface.h @@ -68,6 +68,7 @@ public: bool m_unixTerminalDisabled = false; bool m_useCtrlCStub = false; bool m_belowNormalPriority = false; // internal, dependent on other fields and specific code path + bool m_createConsoleOnWindows = false; }; class QTCREATOR_UTILS_EXPORT ProcessResultData diff --git a/src/libs/utils/processutils.cpp b/src/libs/utils/processutils.cpp index c8394e37dd2..b534d6f8bb2 100644 --- a/src/libs/utils/processutils.cpp +++ b/src/libs/utils/processutils.cpp @@ -45,16 +45,6 @@ void ProcessStartHandler::handleProcessStarted() } } -void ProcessStartHandler::setBelowNormalPriority() -{ -#ifdef Q_OS_WIN - m_process->setCreateProcessArgumentsModifier( - [](QProcess::CreateProcessArguments *args) { - args->flags |= BELOW_NORMAL_PRIORITY_CLASS; - }); -#endif // Q_OS_WIN -} - void ProcessStartHandler::setNativeArguments(const QString &arguments) { #ifdef Q_OS_WIN @@ -65,6 +55,29 @@ void ProcessStartHandler::setNativeArguments(const QString &arguments) #endif // Q_OS_WIN } +void ProcessStartHandler::setWindowsSpecificStartupFlags(bool belowNormalPriority, + bool createConsoleWindow) +{ +#ifdef Q_OS_WIN + if (!belowNormalPriority && !createConsoleWindow) + return; + + m_process->setCreateProcessArgumentsModifier( + [belowNormalPriority, createConsoleWindow](QProcess::CreateProcessArguments *args) { + if (createConsoleWindow) { + args->flags |= CREATE_NEW_CONSOLE; + args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; + } + + if (belowNormalPriority) + args->flags |= BELOW_NORMAL_PRIORITY_CLASS; + }); +#else // Q_OS_WIN + Q_UNUSED(belowNormalPriority) + Q_UNUSED(createConsoleWindow) +#endif +} + #ifdef Q_OS_WIN static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam) { diff --git a/src/libs/utils/processutils.h b/src/libs/utils/processutils.h index 60161f83984..fa915e2ac42 100644 --- a/src/libs/utils/processutils.h +++ b/src/libs/utils/processutils.h @@ -20,8 +20,8 @@ public: QIODevice::OpenMode openMode() const; void handleProcessStart(); void handleProcessStarted(); - void setBelowNormalPriority(); void setNativeArguments(const QString &arguments); + void setWindowsSpecificStartupFlags(bool belowNormalPriority, bool createConsoleWindow); private: ProcessMode m_processMode = ProcessMode::Reader; diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 0ec90d393b4..1583316832b 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -454,9 +454,10 @@ private: ProcessStartHandler *handler = m_process->processStartHandler(); handler->setProcessMode(m_setup.m_processMode); handler->setWriteData(m_setup.m_writeData); - if (m_setup.m_belowNormalPriority) - handler->setBelowNormalPriority(); handler->setNativeArguments(m_setup.m_nativeArguments); + handler->setWindowsSpecificStartupFlags(m_setup.m_belowNormalPriority, + m_setup.m_createConsoleOnWindows); + m_process->setProcessEnvironment(m_setup.m_environment.toProcessEnvironment()); m_process->setWorkingDirectory(m_setup.m_workingDirectory.path()); m_process->setStandardInputFile(m_setup.m_standardInputFile); @@ -1313,6 +1314,16 @@ QString QtcProcess::toStandaloneCommandLine() const return parts.join(" "); } +void QtcProcess::setCreateConsoleOnWindows(bool create) +{ + d->m_setup.m_createConsoleOnWindows = create; +} + +bool QtcProcess::createConsoleOnWindows() const +{ + return d->m_setup.m_createConsoleOnWindows; +} + void QtcProcess::setExtraData(const QString &key, const QVariant &value) { d->m_setup.m_extraData.insert(key, value); diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 9d539f08e20..e016b50d613 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -181,6 +181,9 @@ public: QString toStandaloneCommandLine() const; + void setCreateConsoleOnWindows(bool create); + bool createConsoleOnWindows() const; + signals: void starting(); // On NotRunning -> Starting state transition void started(); // On Starting -> Running state transition diff --git a/src/libs/utils/terminalcommand.cpp b/src/libs/utils/terminalcommand.cpp index c25b379f321..102fc42e05d 100644 --- a/src/libs/utils/terminalcommand.cpp +++ b/src/libs/utils/terminalcommand.cpp @@ -65,13 +65,7 @@ TerminalCommand TerminalCommand::defaultTerminalEmulator() if (defaultTerm.command.isEmpty()) { if (HostOsInfo::isMacHost()) { - const FilePath termCmd = FilePath::fromString(QCoreApplication::applicationDirPath()) - / "../Resources/scripts/openTerminal.py"; - if (termCmd.exists()) - defaultTerm = {termCmd, "", ""}; - else - defaultTerm = {"/usr/X11/bin/xterm", "", "-e"}; - + return {"Terminal.app", "", ""}; } else if (HostOsInfo::isAnyUnixHost()) { defaultTerm = {"xterm", "", "-e"}; const Environment env = Environment::systemEnvironment(); diff --git a/src/libs/utils/terminalhooks.cpp b/src/libs/utils/terminalhooks.cpp index 8187229cbf5..6ee46b33616 100644 --- a/src/libs/utils/terminalhooks.cpp +++ b/src/libs/utils/terminalhooks.cpp @@ -3,10 +3,10 @@ #include "terminalhooks.h" -#include "terminalinterface.h" #include "filepath.h" #include "qtcprocess.h" #include "terminalcommand.h" +#include "terminalinterface.h" #include @@ -14,10 +14,9 @@ namespace Utils::Terminal { FilePath defaultShellForDevice(const FilePath &deviceRoot) { - if (!deviceRoot.needsDevice()) - return {}; + if (deviceRoot.osType() == OsTypeWindows) + return deviceRoot.withNewPath("cmd.exe").searchInPath(); - // TODO: Windows ? const Environment env = deviceRoot.deviceEnvironment(); FilePath shell = FilePath::fromUserInput(env.value_or("SHELL", "/bin/sh")); @@ -41,18 +40,23 @@ class ExternalTerminalProcessImpl final : public TerminalInterface void startStubProcess(const CommandLine &cmd, const ProcessSetupData &) override { + const TerminalCommand terminal = TerminalCommand::terminalEmulator(); + if (HostOsInfo::isWindowsHost()) { m_terminalProcess.setCommand(cmd); QObject::connect(&m_terminalProcess, &QtcProcess::done, this, [this] { m_interface->onStubExited(); }); + m_terminalProcess.setCreateConsoleOnWindows(true); + m_terminalProcess.setProcessMode(ProcessMode::Writer); m_terminalProcess.start(); - } else if (HostOsInfo::isMacHost()) { + } else if (HostOsInfo::isMacHost() && terminal.command == "Terminal.app") { QTemporaryFile f; f.setAutoRemove(false); f.open(); f.setPermissions(QFile::ExeUser | QFile::ReadUser | QFile::WriteUser); f.write("#!/bin/sh\n"); + f.write("clear\n"); f.write(QString("exec '%1' %2\n") .arg(cmd.executable().nativePath()) .arg(cmd.arguments()) @@ -64,11 +68,10 @@ class ExternalTerminalProcessImpl final : public TerminalInterface = QString("tell app \"Terminal\" to do script \"'%1'; rm -f '%1'; exit\"") .arg(path); - m_terminalProcess.setCommand({"osascript", {"-e", exe}}); + m_terminalProcess.setCommand( + {"osascript", {"-e", "tell app \"Terminal\" to activate", "-e", exe}}); m_terminalProcess.runBlocking(); } else { - const TerminalCommand terminal = TerminalCommand::terminalEmulator(); - CommandLine cmdLine = {terminal.command, {terminal.executeArgs}}; cmdLine.addCommandLineAsArgs(cmd, CommandLine::Raw); diff --git a/src/libs/utils/terminalinterface.cpp b/src/libs/utils/terminalinterface.cpp index 7ec7c755fd3..58d48cb910a 100644 --- a/src/libs/utils/terminalinterface.cpp +++ b/src/libs/utils/terminalinterface.cpp @@ -304,8 +304,6 @@ void TerminalInterface::start() return; } - m_setup.m_environment.unset(QLatin1String("TERM")); - Environment finalEnv = m_setup.m_environment; if (HostOsInfo::isWindowsHost()) { @@ -319,6 +317,8 @@ void TerminalInterface::start() if (!systemRoot.isEmpty()) finalEnv.set("SystemRoot", systemRoot); } + } else if (HostOsInfo::isMacHost()) { + finalEnv.set("TERM", "xterm-256color"); } if (finalEnv.hasChanges()) { diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 7bac522c5ba..861a8197ab7 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -294,6 +295,7 @@ void DockerProcessImpl::start() m_process.setExtraData(m_setup.m_extraData); m_process.setStandardInputFile(m_setup.m_standardInputFile); m_process.setAbortOnMetaChars(m_setup.m_abortOnMetaChars); + m_process.setCreateConsoleOnWindows(m_setup.m_createConsoleOnWindows); if (m_setup.m_lowPriority) m_process.setLowPriority(); @@ -403,7 +405,6 @@ DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &dat } QtcProcess *proc = new QtcProcess(d); - proc->setTerminalMode(TerminalMode::On); QObject::connect(proc, &QtcProcess::done, [proc] { if (proc->error() != QProcess::UnknownError && MessageManager::instance()) { @@ -413,10 +414,10 @@ DockerDevice::DockerDevice(DockerSettings *settings, const DockerDeviceData &dat proc->deleteLater(); }); - const QString wd = workingDir.isEmpty() ? "/" : workingDir.path(); - proc->setCommand({settings->dockerBinaryPath.filePath(), - {"exec", "-it", "-w", wd, d->containerId(), "/bin/sh"}}); - proc->setEnvironment(Environment::systemEnvironment()); // The host system env. Intentional. + proc->setTerminalMode(TerminalMode::On); + proc->setEnvironment(env); + proc->setWorkingDirectory(workingDir); + proc->setCommand({Terminal::defaultShellForDevice(rootPath()), {}}); proc->start(); }); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 724b6608aad..4ad0d59d328 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -34,58 +35,11 @@ using namespace Utils; namespace ProjectExplorer { -static void startTerminalEmulator(const QString &workingDir, const Environment &env) -{ -#ifdef Q_OS_WIN - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - - PROCESS_INFORMATION pinfo; - ZeroMemory(&pinfo, sizeof(pinfo)); - - static const auto quoteWinCommand = [](const QString &program) { - const QChar doubleQuote = QLatin1Char('"'); - - // add the program as the first arg ... it works better - QString programName = program; - programName.replace(QLatin1Char('/'), QLatin1Char('\\')); - if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote) - && programName.contains(QLatin1Char(' '))) { - programName.prepend(doubleQuote); - programName.append(doubleQuote); - } - return programName; - }; - const QString cmdLine = quoteWinCommand(qtcEnvironmentVariable("COMSPEC")); - // cmdLine is assumed to be detached - - // https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083 - - const QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null); - LPVOID envPtr = (env != Environment::systemEnvironment()) - ? (WCHAR *)(totalEnvironment.utf16()) : nullptr; - - const bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(), - 0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, - envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(), - &si, &pinfo); - - if (success) { - CloseHandle(pinfo.hThread); - CloseHandle(pinfo.hProcess); - } -#else - const TerminalCommand term = TerminalCommand::terminalEmulator(); - QProcess process; - process.setProgram(term.command.nativePath()); - process.setArguments(ProcessArgs::splitArgs(term.openArgs, HostOsInfo::hostOs())); - process.setProcessEnvironment(env.toProcessEnvironment()); - process.setWorkingDirectory(workingDir); - process.startDetached(); -#endif -} +class DesktopDevicePrivate : public QObject +{}; DesktopDevice::DesktopDevice() + : d(new DesktopDevicePrivate()) { setFileAccess(DesktopDeviceFileAccess::instance()); @@ -102,16 +56,24 @@ DesktopDevice::DesktopDevice() QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END); setFreePorts(Utils::PortList::fromString(portRange)); - setOpenTerminal([](const Environment &env, const FilePath &path) { - const QFileInfo fileInfo = path.toFileInfo(); - const QString workingDir = QDir::toNativeSeparators(fileInfo.isDir() ? - fileInfo.absoluteFilePath() : - fileInfo.absolutePath()); + setOpenTerminal([this](const Environment &env, const FilePath &path) { const Environment realEnv = env.hasChanges() ? env : Environment::systemEnvironment(); - startTerminalEmulator(workingDir, realEnv); + + const FilePath shell = Terminal::defaultShellForDevice(path); + + QtcProcess *process = new QtcProcess(d.get()); + QObject::connect(process, &QtcProcess::done, process, &QtcProcess::deleteLater); + + process->setTerminalMode(TerminalMode::On); + process->setEnvironment(realEnv); + process->setCommand({shell, {}}); + process->setWorkingDirectory(path); + process->start(); }); } +DesktopDevice::~DesktopDevice() = default; + IDevice::DeviceInfo DesktopDevice::deviceInformation() const { return DeviceInfo(); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index ee5ac1ca5eb..28220f21ed6 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h @@ -6,18 +6,22 @@ #include "../projectexplorer_export.h" #include "idevice.h" -#include "idevicefactory.h" #include +#include + namespace ProjectExplorer { class ProjectExplorerPlugin; +class DesktopDevicePrivate; namespace Internal { class DesktopDeviceFactory; } class PROJECTEXPLORER_EXPORT DesktopDevice : public IDevice { public: + ~DesktopDevice() override; + IDevice::DeviceInfo deviceInformation() const override; IDeviceWidget *createWidget() override; @@ -40,6 +44,8 @@ protected: friend class ProjectExplorerPlugin; friend class Internal::DesktopDeviceFactory; + + std::unique_ptr d; }; } // namespace ProjectExplorer diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index a51a7d3bf03..760273e9ab5 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -645,6 +645,8 @@ void SshProcessInterfacePrivate::doStart() m_process.setPtyData(q->m_setup.m_ptyData); m_process.setReaperTimeout(q->m_setup.m_reaperTimeout); m_process.setWriteData(q->m_setup.m_writeData); + m_process.setCreateConsoleOnWindows(q->m_setup.m_createConsoleOnWindows); + // TODO: what about other fields from m_setup? SshParameters::setupSshEnvironment(&m_process); if (!m_sshParameters.x11DisplayName.isEmpty()) { diff --git a/src/plugins/terminal/terminalpane.cpp b/src/plugins/terminal/terminalpane.cpp index dd9cdb5239a..c2467ec71d4 100644 --- a/src/plugins/terminal/terminalpane.cpp +++ b/src/plugins/terminal/terminalpane.cpp @@ -6,6 +6,7 @@ #include "shellmodel.h" #include "terminaltr.h" #include "terminalwidget.h" +#include "utils/terminalhooks.h" #include #include @@ -175,7 +176,6 @@ QWidget *TerminalPane::outputWidget(QWidget *parent) auto terminalWidget = new TerminalWidget(parent); m_tabWidget->addTab(terminalWidget, Tr::tr("Terminal")); setupTerminalWidget(terminalWidget); - } return m_tabWidget; @@ -201,12 +201,13 @@ void TerminalPane::setupTerminalWidget(TerminalWidget *terminal) if (!terminal) return; - auto setTabText = [this](TerminalWidget * terminal) { + auto setTabText = [this](TerminalWidget *terminal) { auto index = m_tabWidget->indexOf(terminal); const FilePath cwd = terminal->cwd(); - const QString exe = terminal->currentCommand().isEmpty() ? terminal->shellName() - : terminal->currentCommand().executable().fileName(); + const QString exe = terminal->currentCommand().isEmpty() + ? terminal->shellName() + : terminal->currentCommand().executable().fileName(); if (cwd.isEmpty()) m_tabWidget->setTabText(index, exe); diff --git a/src/tools/processlauncher/launchersockethandler.cpp b/src/tools/processlauncher/launchersockethandler.cpp index 21167f8d773..a0a2733ded1 100644 --- a/src/tools/processlauncher/launchersockethandler.cpp +++ b/src/tools/processlauncher/launchersockethandler.cpp @@ -172,6 +172,7 @@ void LauncherSocketHandler::handleStartPacket() const auto packet = LauncherPacket::extractPacket( m_packetParser.token(), m_packetParser.packetData()); + process->setEnvironment(packet.env); process->setWorkingDirectory(packet.workingDir); // Forwarding is handled by the LauncherInterface @@ -179,10 +180,10 @@ void LauncherSocketHandler::handleStartPacket() ? QProcess::MergedChannels : QProcess::SeparateChannels); process->setStandardInputFile(packet.standardInputFile); ProcessStartHandler *handler = process->processStartHandler(); + handler->setWindowsSpecificStartupFlags(packet.belowNormalPriority, + packet.createConsoleOnWindows); handler->setProcessMode(packet.processMode); handler->setWriteData(packet.writeData); - if (packet.belowNormalPriority) - handler->setBelowNormalPriority(); handler->setNativeArguments(packet.nativeArguments); if (packet.lowPriority) process->setLowPriority();