[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27. Consoles; Devices; Frames; Windows


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27.1 Introduction to Consoles; Devices; Frames; Windows

A window-system window that you see on the screen is called a frame in Emacs terminology. Each frame is subdivided into one or more non-overlapping panes, called (confusingly) windows. Each window displays the text of a buffer in it. (See above on Buffers.) Note that buffers and windows are independent entities: Two or more windows can be displaying the same buffer (potentially in different locations), and a buffer can be displayed in no windows.

A single display screen that contains one or more frames is called a display. Under most circumstances, there is only one display. However, more than one display can exist, for example if you have a multi-headed console, i.e. one with a single keyboard but multiple displays. (Typically in such a situation, the various displays act like one large display, in that the mouse is only in one of them at a time, and moving the mouse off of one moves it into another.) In some cases, the different displays will have different characteristics, e.g. one color and one mono.

XEmacs can display frames on multiple displays. It can even deal simultaneously with frames on multiple keyboards (called consoles in XEmacs terminology). Here is one case where this might be useful: You are using XEmacs on your workstation at work, and leave it running. Then you go home and dial in on a TTY line, and you can use the already-running XEmacs process to display another frame on your local TTY.

Thus, there is a hierarchy console -> display -> frame -> window. There is a separate Lisp object type for each of these four concepts. Furthermore, there is logically a selected console, selected display, selected frame, and selected window. Each of these objects is distinguished in various ways, such as being the default object for various functions that act on objects of that type. Note that every containing object remembers the “selected” object among the objects that it contains: e.g. not only is there a selected window, but every frame remembers the last window in it that was selected, and changing the selected frame causes the remembered window within it to become the selected window. Similar relationships apply for consoles to devices and devices to frames.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27.2 Point

Recall that every buffer has a current insertion position, called point. Now, two or more windows may be displaying the same buffer, and the text cursor in the two windows (i.e. point) can be in two different places. You may ask, how can that be, since each buffer has only one value of point? The answer is that each window also has a value of point that is squirreled away in it. There is only one selected window, and the value of “point” in that buffer corresponds to that window. When the selected window is changed from one window to another displaying the same buffer, the old value of point is stored into the old window’s “point” and the value of point from the new window is retrieved and made the value of point in the buffer. This means that window-point for the selected window is potentially inaccurate, and if you want to retrieve the correct value of point for a window, you must special-case on the selected window and retrieve the buffer’s point instead. This is related to why save-window-excursion does not save the selected window’s value of point.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27.3 Window Hierarchy

If a frame contains multiple windows (panes), they are always created by splitting an existing window along the horizontal or vertical axis. Terminology is a bit confusing here: to split a window horizontally means to create two side-by-side windows, i.e. to make a vertical cut in a window. Likewise, to split a window vertically means to create two windows, one above the other, by making a horizontal cut.

If you split a window and then split again along the same axis, you will end up with a number of panes all arranged along the same axis. The precise way in which the splits were made should not be important, and this is reflected internally. Internally, all windows are arranged in a tree, consisting of two types of windows, combination windows (which have children, and are covered completely by those children) and leaf windows, which have no children and are visible. Every combination window has two or more children, all arranged along the same axis. There are (logically) two subtypes of windows, depending on whether their children are horizontally or vertically arrayed. There is always one root window, which is either a leaf window (if the frame contains only one window) or a combination window (if the frame contains more than one window). In the latter case, the root window will have two or more children, either horizontally or vertically arrayed, and each of those children will be either a leaf window or another combination window.

Here are some rules:

  1. Horizontal combination windows can never have children that are horizontal combination windows; same for vertical.
  2. Only leaf windows can be split (obviously) and this splitting does one of two things: (a) turns the leaf window into a combination window and creates two new leaf children, or (b) turns the leaf window into one of the two new leaves and creates the other leaf. Rule (1) dictates which of these two outcomes happens.
  3. Every combination window must have at least two children.
  4. Leaf windows can never become combination windows. They can be deleted, however. If this results in a violation of (3), the parent combination window also gets deleted.
  5. All functions that accept windows must be prepared to accept combination windows, and do something sane (e.g. signal an error if so). Combination windows do escape to the Lisp level.
  6. All windows have three fields governing their contents: these are hchild (a list of horizontally-arrayed children), vchild (a list of vertically-arrayed children), and buffer (the buffer contained in a leaf window). Exactly one of these will be non-nil. Remember that horizontally-arrayed means “side-by-side” and vertically-arrayed means one above the other.
  7. Leaf windows also have markers in their start (the first buffer position displayed in the window) and pointm (the window’s stashed value of point—see above) fields, while combination windows have nil in these fields.
  8. The list of children for a window is threaded through the next and prev fields of each child window.
  9. Deleted windows can be undeleted. This happens as a result of restoring a window configuration, and is unlike frames, displays, and consoles, which, once deleted, can never be restored. Deleting a window does nothing except set a special dead bit to 1 and clear out the next, prev, hchild, and vchild fields, for GC purposes.
  10. Most frames actually have two top-level windows—one for the minibuffer and one (the root) for everything else. The modeline (if present) separates these two. The next field of the root points to the minibuffer, and the prev field of the minibuffer points to the root. The other next and prev fields are nil, and the frame points to both of these windows. Minibuffer-less frames have no minibuffer window, and the next and prev of the root window are nil. Minibuffer-only frames have no root window, and the next of the minibuffer window is nil but the prev points to itself. (#### This is an artifact that should be fixed.)

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27.4 The Window Object

Windows have the following accessible fields:

frame

The frame that this window is on.

mini_p

Non-nil if this window is a minibuffer window.

buffer

The buffer that the window is displaying. This may change often during the life of the window.

dedicated

Non-nil if this window is dedicated to its buffer.

pointm

This is the value of point in the current buffer when this window is selected; when it is not selected, it retains its previous value.

start

The position in the buffer that is the first character to be displayed in the window.

force_start

If this flag is non-nil, it says that the window has been scrolled explicitly by the Lisp program. This affects what the next redisplay does if point is off the screen: instead of scrolling the window to show the text around point, it moves point to a location that is on the screen.

last_modified

The modified field of the window’s buffer, as of the last time a redisplay completed in this window.

last_point

The buffer’s value of point, as of the last time a redisplay completed in this window.

left

This is the left-hand edge of the window, measured in columns. (The leftmost column on the screen is column 0.)

top

This is the top edge of the window, measured in lines. (The top line on the screen is line 0.)

height

The height of the window, measured in lines.

width

The width of the window, measured in columns.

next

This is the window that is the next in the chain of siblings. It is nil in a window that is the rightmost or bottommost of a group of siblings.

prev

This is the window that is the previous in the chain of siblings. It is nil in a window that is the leftmost or topmost of a group of siblings.

parent

Internally, XEmacs arranges windows in a tree; each group of siblings has a parent window whose area includes all the siblings. This field points to a window’s parent.

Parent windows do not display buffers, and play little role in display except to shape their child windows. Emacs Lisp programs usually have no access to the parent windows; they operate on the windows at the leaves of the tree, which actually display buffers.

hscroll

This is the number of columns that the display in the window is scrolled horizontally to the left. Normally, this is 0.

use_time

This is the last time that the window was selected. The function get-lru-window uses this field.

display_table

The window’s display table, or nil if none is specified for it.

update_mode_line

Non-nil means this window’s mode line needs to be updated.

base_line_number

The line number of a certain position in the buffer, or nil. This is used for displaying the line number of point in the mode line.

base_line_pos

The position in the buffer for which the line number is known, or nil meaning none is known.

region_showing

If the region (or part of it) is highlighted in this window, this field holds the mark position that made one end of that region. Otherwise, this field is nil.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

27.5 Modules for the Basic Displayable Lisp Objects

 
console-msw.c’
‘console-msw.h’
‘console-stream.c’
‘console-stream.h’
‘console-tty.c’
‘console-tty.h’
‘console-x.c’
‘console-x.h’
‘console.c’
‘console.h

These modules implement the console Lisp object type. A console contains multiple display devices, but only one keyboard and mouse. Most of the time, a console will contain exactly one device.

This model may no longer suffice. The X Window System (at least) now supports a variety of input devices, including touchscreens and tablets, as well as the traditional keyboard and mouse, and may even be able to support multiple instances of a single type of input device (especially pointing devices) on a single console.

Consoles are the top of a lisp object inclusion hierarchy. Consoles contain devices, which contain frames, which contain windows.

 
device-msw.c’
‘device-tty.c’
‘device-x.c’
‘device.c’
‘device.h

These modules implement the device Lisp object type. This abstracts a particular screen or connection on which frames are displayed. As with Lisp objects, event interfaces, and other subsystems, the device code is separated into a generic component that contains a standardized interface (in the form of a set of methods) onto particular device types.

The device subsystem defines all the methods and provides method services for not only device operations but also for the frame, window, menubar, scrollbar, toolbar, and other displayable-object subsystems. The reason for this is that all of these subsystems have the same subtypes (X, TTY, Microsoft Windows, etc.) as devices do.

This abstraction is probably broken (as of late 2004), at least for X consoles, with the advent of the Xft library. Xft is a complete break from the traditional approach to text rendering in the X11 environment, since fonts are composed of glyphs rendered by client-side code. These glyphs are then transmitted to the server as sets of trapezoids, and displayed by the XRender extension (where available; the X11 core protocol can also be used, but this is slow). The XRender extension is especially attractive because it allows modern image composition techniques to be used to render antialiased fonts.

By contrast, the traditional approach renders fonts on the server side as a collection of bitmaps. It is also possible use a font server that knows how to render antialiased fonts, but for some reason this approach has never caught on.

The problem that this creates for XEmacs is that the traditional (and still popular) widget sets, the various Athena variants and the Motif widget set, are based on the server-side rendering model. Thus, even if XEmacs-specific widgets (such as the basic text window, the Lucid menubar, and the recently added tab control) can be adapted to render text via Xft, older widgets (such as buttons and labels) and “modern” widgets derived from traditional widgets (the progress gauge) still expect their font resources to be converted to server-side fonts. Then text is rendered by calls to the core protocol via Xlib, rather than by calls to the XRender protocol via Xft.

It’s even possible to imagine a situation where a widget is composed of components which draw their own text (predefined widgets) as well as new components which can draw using more modern methods. Handling this will either require reworking the Emacs face mechanism to provide a way to determine whether this widget can use that font, or ways to give each of several different widgets, even different components of a given widget, a different face property. This is already an issue, as widgets generally derive their font from the gui-element face, but this might not be appropriate for widgets embedded in a buffer.

There seem to be two overall ways to go.

  1. Add face information to the Lucid widget library, and extend the coverage of that library to device types that aren’t supported by it yet (MS Windows, and maybe TTY).
  2. Create a lighter-weight interface, perhaps an extension of the device interface, that allows widgets to access face information from the device it is implemented on.
 
frame-msw.c’
‘frame-tty.c’
‘frame-x.c’
‘frame.c’
‘frame.h

Each device contains one or more frames in which objects (e.g. text) are displayed. A frame corresponds to a window in the window system; usually this is a top-level window but it could potentially be one of a number of overlapping child windows within a top-level window, using the MDI (Multiple Document Interface) protocol in Microsoft Windows or a similar scheme.

The ‘frame-*’ files implement the frame Lisp object type and provide the generic and device-type-specific operations on frames (e.g. raising, lowering, resizing, moving, etc.).

 
window.c’
‘window.h

Each frame consists of one or more non-overlapping windows (better known as panes in standard window-system terminology) in which a buffer’s text can be displayed. Windows can also have scrollbars displayed around their edges.

window.c’ and ‘window.h’ implement the window Lisp object type and provide code to manage windows. Since windows have no associated resources in the window system (the window system knows only about the frame; no child windows or anything are used for XEmacs windows), there is no device-type-specific code here; all of that code is part of the redisplay mechanism or the code for particular object types such as scrollbars.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Aidan Kehoe on December 27, 2016 using texi2html 1.82.