A [[frame]] contains and displays one or more Emacs internal [[window]]s.

Frames have names, similar to how buffers have names.  Additionally, on GUIs, there is a ''frame title'', typically shown by the host GUI in a "title bar" above the Emacs frame.  There is also a separate ''icon title'', for iconified/minimized representations of Emacs frames.

To have the Emacs frame title appear in the title bar of a character terminal, see XTermTitle.

== Standard behavior ==

The frame title is determined by the variable `frame-title-format'.  Likewise, the icon title comes from`icon-title-format'.  They are both [[ModeLineConstruct]]s, similar to the `mode-line-format' variable.  Most commonly, they are set to a string, or a list whose elements will be recursively processed and concatenated together.

Mode line constructs can use [PercentConstruct %-constructs] to insert information.  Two of the most common forms are ##%f## for the full file path, and the ##%b## for the buffer name.

The default `frame-title-format' (as of Emacs 27.1, circa 2020) is:

    (multiple-frames "%b" ("" invocation-name "@" system-name))

In effect, if there are multiple Emacs frames (multiple external GUI windows), the buffer name is used as the frame title; otherwise, something like ##Emacs@foo## is used.

=== Caveats ===

If the current buffer has no associated file (for example, ##*scratch*## and dired buffers), then ##%f## will be blank.  Thus ##%f## used alone can produce confusing results.

##%## constructs which indicate line or column number of point (##%l##, ##%c##, ##%C##) are ignored in frame and icon title formats.

See also the Lisp usage tips in ModeLineConstruct.

== Renaming frames ==

Library <tt>[[frame-cmds.el]]</tt> contains two commands for renaming [[frame]]s:

* '''`rename-frame'''' - Rename a frame named ##OLD-NAME## to ##NEW-NAME##.
: Prefix arg ##ALL-NAMED## non-`nil' means rename all frames named ##FRAME## to ##NEWNAME##.
: ##OLD-NAME## can be a frame, its name, or `nil'.  Default is `selected-frame'.
: ##NEW-NAME## is a string or `nil'.  Default ##NEW-NAME## is current `buffer-name'.

* '''`rename-non-minibuffer-frame'''' - Unless ##OLD-NAME## names the `minibuffer-frame', use `rename-frame'
to rename a frame named ##OLD-NAME## to ##NEW-NAME##.
: Prefix arg ##ALL-NAMED## non-`nil' means rename all frames named ##FRAME## to ##NEWNAME##.
: ##OLD-NAME## can be a frame, its name, or `nil'.  Default is `selected-frame'.
: ##NEW-NAME## is a string or `nil'.  Default ##NEW-NAME## is current `buffer-name'.

== Example customizations ==

These would generally be placed in one's InitFile, to take effect for every Emacs session.  However, you can also use them in LispInteractionMode.  This may be useful to test and tune to your liking, before you save the finished result.

=== Static text ===

The simplest possible frame title would likely be some text which never changes -- always the same, regardless of frame, buffer, window, or anything else.

    (setq frame-title-format "Hello world")

=== Simple format string ===

Moving up one step in complexity would be a simple string that makes use of [PercentConstruct %-constructs].  A very simple example might be this, which uses the buffer name as the frame title:

    (setq frame-title-format "%b")

More than one specifier can be given.  This shows the buffer name first, followed by the full file path (if any) in angle brackets:

    (setq frame-title-format "%b <%f>")

Note that %-constructs are not expanded if contained within a Lisp symbol whose value is a string; see [[ModeLineConstruct#NestedStrings]] for details.


=== Buffer name and Emacs version ===

Here are two similar examples, both of which display the buffer name and Emacs version.

    (setq frame-title-format '("" "%b @ Emacs " emacs-version))
    (setq frame-title-format '("" "[%b] - Emacs " emacs-version))

They would render something like:

    *scratch* @ Emacs 27.1
    [*scratch*] @ Emacs 27.1

=== User and host ===

A popular desire is to put some variation on ##user@host## in the frame title (where "host" means "name of the computer").

==== Lisp symbols ====

This method uses Emacs Lisp symbols, rather than host OS environment strings, to obtain username and hostname.  This may, in theory, be more portable across different OSes.  To provide just the user and host:

    (setq frame-title-format (list user-login-name "@" system-name))

One can combine this with % constructs.  For example, this puts the buffer name first, with the user and host following in parenthesis:

    (setq frame-title-format (list "%b (" user-login-name "@" system-name ")"))

That might render as:

    *scratch* (jsmith@darkstar)

==== Environment variables ====

A common but perhaps less portable approach is to query the host OS environment variables directly.  Problems can arise because not all systems use the same variable names in the same way.  None the less, an example that works on many Unix-like systems is:

    (setq frame-title-format (list "%b - " (getenv "USER") "@" (getenv "HOSTNAME")))

This shows the buffer name followed by user@host, separated by a literal dash (##-##).

==== Microsoft Windows ====

Microsoft Windows does not use the same variable names as Unix-like systems.  To get a similar result as the above, one would need to use:

    (setq frame-title-format (list "%b - " (getenv "USERNAME") "@" (getenv "COMPUTERNAME")))

==== Hostname via command ====

Reportedly some versions of Ubuntu Linux do not export ##HOSTNAME## by default (one can check with ##export -p##).  One suggestion was to use the external command ##hostname(1)## during Emacs startup to determine the hostname, and then reference that in the frame title.

    (setq my-hostname 
      (replace-regexp-in-string "\\(^[[:space:]\n]*\\|[[:space:]\n]*$\\)" "" ;; like perl chomp()
        (with-output-to-string 
           (call-process "/bin/hostname" nil standard-output nil))))
    (setq my-username (getenv "USER"))
    (setq frame-title-format (list "%b - " my-username "@" my-hostname))

=== ErcChannelTracking ===

If you're an ErcChannelTracking fan, take a look at:

    (setq frame-title-format '("" erc-modified-channels-object "%b @ Emacs " emacs-version))

=== Frame and icon ===

To set both frame and icon title to the same thing, which also tells if you are using GnuEmacs or [[XEmacs]]:

    (setq frame-title-format
          (setq icon-title-format
                (format "%%b - %semacs" (if (featurep 'xemacs) "x" ""))))

=== Date and time ===

Display date/time if `display-time-mode' is set:

    (setq frame-title-format '("" invocation-name "@" system-name "     "
      global-mode-string "     %f" ))

See also `display-time-format' and `mode-line-format'.

=== Date, Time, Week Number and Buffer Name ===
I find it useful to know the time, date and week numbers as I'm working in Emacs. Week numbers are especially important to me, as this is my primary productivity blocks (every week of the year get its own org file).

The code below evaluates ##format-time-string## as a yyyy-mm-dd.hhmm format, followed by the week. After this is evaluated, the buffer name, ##%b##, is added.

{{{
(setq frame-title-format '("%b " (:eval (format-time-string "%Y-%m-%d.%H%M w:%U"))))
}}}

Notice the usage of ##:eval##, which continues to evaluate the date each time it's called (each time a frame is created). Without it, we will get a static format time string that won't change.

For more detailed explanation, check the help documentation on ##mode-line-format##. It contains the different contacts to be used. 

=== Directory, file, or buffer name ===

Full directory path name for DirEd, full file path name for files, buffer name otherwise.

    (setq frame-title-format
          '(buffer-file-name "%f"
            (dired-directory dired-directory "%b")))

To abbreviate the file path name.

    (setq frame-title-format
          '(buffer-file-name (:eval (abbreviate-file-name buffer-file-name))
            (dired-directory dired-directory "%b")))


=== Mark modified buffer ===

This puts a bullet point (•) after the buffer name, if there are unsaved changes.

  (setq frame-title-format
    '((:eval (if (buffer-file-name)
                  (abbreviate-file-name (buffer-file-name))
                    "%b"))
      (:eval (if (buffer-modified-p) 
                 " •"))
      " - Emacs")
  )

=== Buffer name with full path ===

If you already show directories in the buffer name, you may want to use a simpler format:

  (setq uniquify-buffer-name-style 'post-forward
             uniquify-min-dir-content 7))
  
  (setq frame-title-format '("%b"))

=== All buffers displayed in a frame ===

  (defun generate-frame-title ()
    (let ((retval ""))
      (walk-window-tree (lambda (x) (setf retval (seq-concatenate 'string (buffer-name (window-buffer x)) "  " retval))))
      (setf (frame-parameter nil 'name) retval)
     retval))
  (setq-default frame-title-format '(:eval (generate-frame-title)))



== See also ==

* ModeLineConstruct
* PercentConstruct
* ModeLine
* HeaderLine
* ModeLineConfiguration
* Emacs Lisp Reference Manual: [[Manual:Mode Line Format]]
* Emacs Lisp Reference Manual: [[Manual:Mode Line Data]]

----
CategoryFrames CategoryDisplay FrameModes
