File indexing completed on 2024-05-19 05:28:19

0001 /*
0002     This file is part of Konsole, an X terminal.
0003 
0004     SPDX-FileCopyrightText: 2007 Robert Knight <robertknight@gmail.com>
0005     SPDX-FileCopyrightText: 1997, 1998 Lars Doelle <lars.doelle@on-line.de>
0006 
0007     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 
0011     This program is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014     GNU General Public License for more details.
0015 
0016     You should have received a copy of the GNU General Public License
0017     along with this program; if not, write to the Free Software
0018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0019     02110-1301  USA.
0020 */
0021 
0022 #ifndef SESSION_H
0023 #define SESSION_H
0024 
0025 #include <QStringList>
0026 #include <QWidget>
0027 
0028 #include "Emulation.h"
0029 #include "History.h"
0030 #include "ProcessInfo.h"
0031 
0032 class KProcess;
0033 
0034 namespace Konsole
0035 {
0036 
0037 class Emulation;
0038 class Pty;
0039 class TerminalDisplay;
0040 // class ZModemDialog;
0041 
0042 /**
0043  * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
0044  * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.
0045  * The terminal emulation ( Emulation and subclasses ) processes the output stream from the
0046  * PTY and produces a character image which is then shown on views connected to the session.
0047  *
0048  * Each Session can be connected to one or more views by using the addView() method.
0049  * The attached views can then display output from the program running in the terminal
0050  * or send input to the program in the terminal in the form of keypresses and mouse
0051  * activity.
0052  */
0053 class Session : public QObject
0054 {
0055     Q_OBJECT
0056 
0057 public:
0058     Q_PROPERTY(QString name READ nameTitle)
0059     Q_PROPERTY(int processId READ processId)
0060     Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
0061     Q_PROPERTY(QSize size READ size WRITE setSize)
0062 
0063     /**
0064      * Constructs a new session.
0065      *
0066      * To start the terminal process, call the run() method,
0067      * after specifying the program and arguments
0068      * using setProgram() and setArguments()
0069      *
0070      * If no program or arguments are specified explicitly, the Session
0071      * falls back to using the program specified in the SHELL environment
0072      * variable.
0073      */
0074     Session(QObject *parent = nullptr);
0075     ~Session() override;
0076 
0077     /**
0078      * Returns true if the session is currently running.  This will be true
0079      * after run() has been called successfully.
0080      */
0081     bool isRunning() const;
0082 
0083     /**
0084      * Sets the profile associated with this session.
0085      *
0086      * @param profileKey A key which can be used to obtain the current
0087      * profile settings from the SessionManager
0088      */
0089     void setProfileKey(const QString &profileKey);
0090     /**
0091      * Returns the profile key associated with this session.
0092      * This can be passed to the SessionManager to obtain the current
0093      * profile settings.
0094      */
0095     QString profileKey() const;
0096 
0097     /**
0098      * Adds a new view for this session.
0099      *
0100      * The viewing widget will display the output from the terminal and
0101      * input from the viewing widget (key presses, mouse activity etc.)
0102      * will be sent to the terminal.
0103      *
0104      * Views can be removed using removeView().  The session is automatically
0105      * closed when the last view is removed.
0106      */
0107     void setView(TerminalDisplay *widget);
0108     /**
0109      * Removes a view from this session.  When the last view is removed,
0110      * the session will be closed automatically.
0111      *
0112      * @p widget will no longer display output from or send input
0113      * to the terminal
0114      */
0115     void removeView(TerminalDisplay *widget);
0116 
0117     /**
0118      * Returns the view connected to this session
0119      */
0120     TerminalDisplay *view() const;
0121 
0122     /**
0123      * Returns the terminal emulation instance being used to encode / decode
0124      * characters to / from the process.
0125      */
0126     Emulation *emulation() const;
0127 
0128     /**
0129      * Returns the environment of this session as a list of strings like
0130      * VARIABLE=VALUE
0131      */
0132     QStringList environment() const;
0133     /**
0134      * Sets the environment for this session.
0135      * @p environment should be a list of strings like
0136      * VARIABLE=VALUE
0137      */
0138     void setEnvironment(const QStringList &environment);
0139 
0140     /** Returns the unique ID for this session. */
0141     int sessionId() const;
0142 
0143     /**
0144      * Return the session title set by the user (ie. the program running
0145      * in the terminal), or an empty string if the user has not set a custom title
0146      */
0147     QString userTitle() const;
0148 
0149     /**
0150      * This enum describes the contexts for which separate
0151      * tab title formats may be specified.
0152      */
0153     enum TabTitleContext {
0154         /** Default tab title format */
0155         LocalTabTitle,
0156         /**
0157          * Tab title format used session currently contains
0158          * a connection to a remote computer (via SSH)
0159          */
0160         RemoteTabTitle
0161     };
0162     /**
0163      * Sets the format used by this session for tab titles.
0164      *
0165      * @param context The context whoose format should be set.
0166      * @param format The tab title format.  This may be a mixture
0167      * of plain text and dynamic elements denoted by a '%' character
0168      * followed by a letter.  (eg. %d for directory).  The dynamic
0169      * elements available depend on the @p context
0170      */
0171     void setTabTitleFormat(TabTitleContext context, const QString &format);
0172     /** Returns the format used by this session for tab titles. */
0173     QString tabTitleFormat(TabTitleContext context) const;
0174 
0175     /** Returns the arguments passed to the shell process when run() is called. */
0176     QStringList arguments() const;
0177     /** Returns the program name of the shell process started when run() is called. */
0178     QString program() const;
0179 
0180     /**
0181      * Sets the command line arguments which the session's program will be passed when
0182      * run() is called.
0183      */
0184     void setArguments(const QStringList &arguments);
0185     /** Sets the program to be executed when run() is called. */
0186     void setProgram(const QString &program);
0187 
0188     /** Returns the session's current working directory. */
0189     QString initialWorkingDirectory()
0190     {
0191         return _initialWorkingDir;
0192     }
0193 
0194     /**
0195      * Sets the initial working directory for the session when it is run
0196      * This has no effect once the session has been started.
0197      */
0198     void setInitialWorkingDirectory(const QString &dir);
0199 
0200     /**
0201      * Sets the type of history store used by this session.
0202      * Lines of output produced by the terminal are added
0203      * to the history store.  The type of history store
0204      * used affects the number of lines which can be
0205      * remembered before they are lost and the storage
0206      * (in memory, on-disk etc.) used.
0207      */
0208     void setHistoryType(const HistoryType &type);
0209     /**
0210      * Returns the type of history store used by this session.
0211      */
0212     const HistoryType &historyType() const;
0213     /**
0214      * Clears the history store used by this session.
0215      */
0216     void clearHistory();
0217 
0218     /**
0219      * Enables monitoring for activity in the session.
0220      * This will cause notifySessionState() to be emitted
0221      * with the NOTIFYACTIVITY state flag when output is
0222      * received from the terminal.
0223      */
0224     void setMonitorActivity(bool);
0225     /** Returns true if monitoring for activity is enabled. */
0226     bool isMonitorActivity() const;
0227 
0228     /**
0229      * Enables monitoring for silence in the session.
0230      * This will cause notifySessionState() to be emitted
0231      * with the NOTIFYSILENCE state flag when output is not
0232      * received from the terminal for a certain period of
0233      * time, specified with setMonitorSilenceSeconds()
0234      */
0235     void setMonitorSilence(bool);
0236     /**
0237      * Returns true if monitoring for inactivity (silence)
0238      * in the session is enabled.
0239      */
0240     bool isMonitorSilence() const;
0241     /** See setMonitorSilence() */
0242     void setMonitorSilenceSeconds(int seconds);
0243 
0244     /**
0245      * Sets the key bindings used by this session.  The bindings
0246      * specify how input key sequences are translated into
0247      * the character stream which is sent to the terminal.
0248      *
0249      * @param id The name of the key bindings to use.  The
0250      * names of available key bindings can be determined using the
0251      * KeyboardTranslatorManager class.
0252      */
0253     void setKeyBindings(const QString &id);
0254     /** Returns the name of the key bindings used by this session. */
0255     QString keyBindings() const;
0256 
0257     /**
0258      * This enum describes the available title roles.
0259      */
0260     enum TitleRole {
0261         /** The name of the session. */
0262         NameRole,
0263         /** The title of the session which is displayed in tabs etc. */
0264         DisplayedTitleRole
0265     };
0266 
0267     /** Sets the session's title for the specified @p role to @p title. */
0268     void setTitle(TitleRole role, const QString &title);
0269     /** Returns the session's title for the specified @p role. */
0270     QString title(TitleRole role) const;
0271     /** Convenience method used to read the name property.  Returns title(Session::NameRole). */
0272     QString nameTitle() const
0273     {
0274         return title(Session::NameRole);
0275     }
0276 
0277     /** Sets the name of the icon associated with this session. */
0278     void setIconName(const QString &iconName);
0279     /** Returns the name of the icon associated with this session. */
0280     QString iconName() const;
0281 
0282     /** Sets the text of the icon associated with this session. */
0283     void setIconText(const QString &iconText);
0284     /** Returns the text of the icon associated with this session. */
0285     QString iconText() const;
0286 
0287     /** Flag if the title/icon was changed by user/shell. */
0288     bool isTitleChanged() const;
0289 
0290     /** Specifies whether a utmp entry should be created for the pty used by this session. */
0291     void setAddToUtmp(bool);
0292 
0293     /** Sends the specified @p signal to the terminal process. */
0294     bool sendSignal(int signal);
0295 
0296     /**
0297      * Specifies whether to close the session automatically when the terminal
0298      * process terminates.
0299      */
0300     void setAutoClose(bool b)
0301     {
0302         _autoClose = b;
0303     }
0304 
0305     /**
0306      * Sets whether flow control is enabled for this terminal
0307      * session.
0308      */
0309     void setFlowControlEnabled(bool enabled);
0310 
0311     /** Returns whether flow control is enabled for this terminal session. */
0312     bool flowControlEnabled() const;
0313 
0314     /**
0315      * Sends @p text to the current foreground terminal program.
0316      */
0317     void sendText(const QString &text) const;
0318 
0319     void sendKeyEvent(QKeyEvent *e) const;
0320 
0321     /**
0322      * Returns the process id of the terminal process.
0323      * This is the id used by the system API to refer to the process.
0324      */
0325     int processId() const;
0326 
0327     /**
0328      * Returns the process id of the terminal's foreground process.
0329      * This is initially the same as processId() but can change
0330      * as the user starts other programs inside the terminal.
0331      */
0332     int foregroundProcessId() const;
0333 
0334     /**
0335      * Returns the name of the terminal's foreground process.
0336      */
0337     QString foregroundProcessName();
0338 
0339     /**
0340      * Returns the current working directory of the process.
0341      */
0342     QString currentDir();
0343 
0344     /** Returns the terminal session's window size in lines and columns. */
0345     QSize size();
0346     /**
0347      * Emits a request to resize the session to accommodate
0348      * the specified window size.
0349      *
0350      * @param size The size in lines and columns to request.
0351      */
0352     void setSize(const QSize &size);
0353 
0354     /** Sets the text codec used by this session's terminal emulation. */
0355     void setCodec(QTextCodec *codec) const;
0356 
0357     /**
0358      * Sets whether the session has a dark background or not.  The session
0359      * uses this information to set the COLORFGBG variable in the process's
0360      * environment, which allows the programs running in the terminal to determine
0361      * whether the background is light or dark and use appropriate colors by default.
0362      *
0363      * This has no effect once the session is running.
0364      */
0365     void setDarkBackground(bool darkBackground);
0366     /**
0367      * Returns true if the session has a dark background.
0368      * See setDarkBackground()
0369      */
0370     bool hasDarkBackground() const;
0371 
0372     /**
0373      * Attempts to get the shell program to redraw the current display area.
0374      * This can be used after clearing the screen, for example, to get the
0375      * shell to redraw the prompt line.
0376      */
0377     void refresh();
0378 
0379     //  void startZModem(const QString &rz, const QString &dir, const QStringList &list);
0380     //  void cancelZModem();
0381     //  bool isZModemBusy() { return _zmodemBusy; }
0382 
0383     /**
0384      * Returns a pty slave file descriptor.
0385      * This can be used for display and control
0386      * a remote terminal.
0387      */
0388     int getPtySlaveFd() const;
0389 
0390 public Q_SLOTS:
0391 
0392     /**
0393      * Starts the terminal session.
0394      *
0395      * This creates the terminal process and connects the teletype to it.
0396      */
0397     void run();
0398 
0399     /**
0400      * Starts the terminal session for "as is" PTY
0401      * (without the direction a data to internal terminal process).
0402      * It can be used for control or display a remote/external terminal.
0403      */
0404     void runEmptyPTY();
0405 
0406     /**
0407      * Closes the terminal session.  This sends a hangup signal
0408      * (SIGHUP) to the terminal process and causes the done(Session*)
0409      * signal to be emitted.
0410      */
0411     void close();
0412 
0413     /**
0414      * Changes the session title or other customizable aspects of the terminal
0415      * emulation display. For a list of what may be changed see the
0416      * Emulation::titleChanged() signal.
0417      */
0418     void setUserTitle(int, const QString &caption);
0419 
0420 Q_SIGNALS:
0421 
0422     /** Emitted when the terminal process starts. */
0423     void started();
0424 
0425     /**
0426      * Emitted when the terminal process exits.
0427      */
0428     void finished();
0429 
0430     /**
0431      * Emitted when output is received from the terminal process.
0432      */
0433     void receivedData(const QString &text);
0434 
0435     /** Emitted when the session's title has changed. */
0436     void titleChanged();
0437 
0438     /** Emitted when the session's profile has changed. */
0439     void profileChanged(const QString &profile);
0440 
0441     /**
0442      * Emitted when the activity state of this session changes.
0443      *
0444      * @param state The new state of the session.  This may be one
0445      * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY
0446      */
0447     void stateChanged(int state);
0448 
0449     /** Emitted when a bell event occurs in the session. */
0450     void bellRequest(const QString &message);
0451 
0452     /**
0453      * Requests that the color the text for any tabs associated with
0454      * this session should be changed;
0455      *
0456      * TODO: Document what the parameter does
0457      */
0458     void changeTabTextColorRequest(int);
0459 
0460     /**
0461      * Requests that the background color of views on this session
0462      * should be changed.
0463      */
0464     void changeBackgroundColorRequest(const QColor &);
0465 
0466     /** TODO: Document me. */
0467     void openUrlRequest(const QString &url);
0468 
0469     /** TODO: Document me. */
0470     //  void zmodemDetected();
0471 
0472     /**
0473      * Emitted when the terminal process requests a change
0474      * in the size of the terminal window.
0475      *
0476      * @param size The requested window size in terms of lines and columns.
0477      */
0478     void resizeRequest(const QSize &size);
0479 
0480     /**
0481      * Emitted when a profile change command is received from the terminal.
0482      *
0483      * @param text The text of the command.  This is a string of the form
0484      * "PropertyName=Value;PropertyName=Value ..."
0485      */
0486     void profileChangeCommandReceived(const QString &text);
0487 
0488     /**
0489      * Emitted when the flow control state changes.
0490      *
0491      * @param enabled True if flow control is enabled or false otherwise.
0492      */
0493     void flowControlEnabledChanged(bool enabled);
0494 
0495     /**
0496      * Broker for Emulation::cursorChanged() signal
0497      */
0498     void cursorChanged(Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled);
0499 
0500     void silence();
0501     void activity();
0502 
0503 private Q_SLOTS:
0504     void done(int);
0505 
0506     //  void fireZModemDetected();
0507 
0508     void onReceiveBlock(const char *buffer, int len);
0509     void monitorTimerDone();
0510 
0511     void onViewSizeChange(int height, int width);
0512     void onEmulationSizeChange(QSize);
0513 
0514     void activityStateSet(int);
0515 
0516     // automatically detach views from sessions when view is destroyed
0517     void viewDestroyed(QObject *view);
0518 
0519     //  void zmodemReadStatus();
0520     //  void zmodemReadAndSendBlock();
0521     //  void zmodemRcvBlock(const char *data, int len);
0522     //  void zmodemFinished();
0523 
0524 private:
0525     void updateTerminalSize();
0526     bool updateForegroundProcessInfo();
0527     WId windowId() const;
0528 
0529     int _uniqueIdentifier;
0530 
0531     std::unique_ptr<Pty> _shellProcess;
0532     std::unique_ptr<Emulation> _emulation;
0533 
0534     TerminalDisplay *_view = nullptr;
0535 
0536     bool _monitorActivity;
0537     bool _monitorSilence;
0538     bool _notifiedActivity;
0539     bool _masterMode;
0540     bool _autoClose;
0541     bool _wantedClose;
0542     QTimer *_monitorTimer;
0543 
0544     int _silenceSeconds;
0545 
0546     QString _nameTitle;
0547     QString _displayTitle;
0548     QString _userTitle;
0549 
0550     QString _localTabTitleFormat;
0551     QString _remoteTabTitleFormat;
0552 
0553     QString _iconName;
0554     QString _iconText; // as set by: echo -en '\033]1;IconText\007
0555     bool _isTitleChanged; ///< flag if the title/icon was changed by user
0556     bool _addToUtmp;
0557     bool _flowControl;
0558     bool _fullScripting;
0559 
0560     QString _program;
0561     QStringList _arguments;
0562 
0563     QStringList _environment;
0564     int _sessionId;
0565 
0566     QString _initialWorkingDir;
0567 
0568     // ZModem
0569     //  bool           _zmodemBusy;
0570     //  KProcess*      _zmodemProc;
0571     //  ZModemDialog*  _zmodemProgress;
0572 
0573     // Color/Font Changes by ESC Sequences
0574 
0575     QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007
0576 
0577     QString _profileKey;
0578 
0579     bool _hasDarkBackground;
0580 
0581     std::unique_ptr<ProcessInfo> _foregroundProcessInfo;
0582     int _foregroundPid;
0583     static int lastSessionId;
0584     int ptySlaveFd;
0585 };
0586 
0587 /**
0588  * Provides a group of sessions which is divided into master and slave sessions.
0589  * Activity in master sessions can be propagated to all sessions within the group.
0590  * The type of activity which is propagated and method of propagation is controlled
0591  * by the masterMode() flags.
0592  */
0593 class SessionGroup : public QObject
0594 {
0595     Q_OBJECT
0596 
0597 public:
0598     /** Constructs an empty session group. */
0599     SessionGroup();
0600     /** Destroys the session group and removes all connections between master and slave sessions. */
0601     ~SessionGroup() override;
0602 
0603     /** Adds a session to the group. */
0604     void addSession(Session *session);
0605     /** Removes a session from the group. */
0606     void removeSession(Session *session);
0607 
0608     /** Returns the list of sessions currently in the group. */
0609     QList<Session *> sessions() const;
0610 
0611     /**
0612      * Sets whether a particular session is a master within the group.
0613      * Changes or activity in the group's master sessions may be propagated
0614      * to all the sessions in the group, depending on the current masterMode()
0615      *
0616      * @param session The session whoose master status should be changed.
0617      * @param master True to make this session a master or false otherwise
0618      */
0619     void setMasterStatus(Session *session, bool master);
0620     /** Returns the master status of a session.  See setMasterStatus() */
0621     bool masterStatus(Session *session) const;
0622 
0623     /**
0624      * This enum describes the options for propagating certain activity or
0625      * changes in the group's master sessions to all sessions in the group.
0626      */
0627     enum MasterMode {
0628         /**
0629          * Any input key presses in the master sessions are sent to all
0630          * sessions in the group.
0631          */
0632         CopyInputToAll = 1
0633     };
0634 
0635     /**
0636      * Specifies which activity in the group's master sessions is propagated
0637      * to all sessions in the group.
0638      *
0639      * @param mode A bitwise OR of MasterMode flags.
0640      */
0641     void setMasterMode(int mode);
0642     /**
0643      * Returns a bitwise OR of the active MasterMode flags for this group.
0644      * See setMasterMode()
0645      */
0646     int masterMode() const;
0647 
0648 private:
0649     void connectPair(Session *master, Session *other) const;
0650     void disconnectPair(Session *master, Session *other) const;
0651     void connectAll(bool connect);
0652     QList<Session *> masters() const;
0653 
0654     // maps sessions to their master status
0655     QHash<Session *, bool> _sessions;
0656 
0657     int _masterMode;
0658 };
0659 
0660 }
0661 
0662 #endif