| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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] | [ ? ] |
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] | [ ? ] |
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:
nil. Remember that horizontally-arrayed
means "side-by-side" and vertically-arrayed means
one above the other.
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.
next and prev fields of each child window.
dead bit to 1 and clear out the
next, prev, hchild, and vchild fields, for
GC purposes.
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] | [ ? ] |
Windows have the following accessible fields:
frame
mini_p
nil if this window is a minibuffer window.
buffer
dedicated
nil if this window is dedicated to its buffer.
pointm
start
force_start
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
modified field of the window's buffer, as of the last time
a redisplay completed in this window.
last_point
left
top
height
width
next
nil in a window that is the rightmost or bottommost of a group of
siblings.
prev
nil in a window that is the leftmost or topmost of a group of
siblings.
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
use_time
get-lru-window uses this field.
display_table
nil if none is specified for it.
update_mode_line
nil means this window's mode line needs to be updated.
base_line_number
nil.
This is used for displaying the line number of point in the mode line.
base_line_pos
nil meaning none is known.
region_showing
nil.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Unfortunately, at the present time, only the console abstraction is at all well-maintained. Device and frame internals are referred to from many places in the redisplay and console code. The best that can be done therefore is to create a whole new console type, even though much code will be shared. (Ben Wing has complained about the code duplication in the GTK+ v1 console, and probably would not be happy with the unpublished Qt console or Andrew Choi's Carbon console, but it's hard to see how those consoles could have been done better without fixing the abstractions in the X (actually Xt), MS Windows, and tty consoles as well as doing a complete refactoring of the console, device, and frame code.)
What is desireable is sharing console, device, and frame methods across platforms in a more general way, reducing the amount of duplicated code by pulling it back into the redisplay engine proper or the Lisp modules as appropriate. For example, we should be able to use `make-frame-on-device' to share a single X connection among GTK, X, and Xft frames. Xft is partially implemented, but GTK would be much harder (impossible?) because it has its own event loop. (Xft shares the Xt event loop with the X console.)
The way all methods get added to the console type is uncool. A console should be a composite, which indicates a collection of I/O resources "used together." It should indicate where operations that change "focus" search for targets, i.e., by default new frames are created on the selected device of the console where the input that invoked the command was received, `pop-to-buffer-other-window' only considers existing windows on the same device of the same console, etc. But it should be possible to assemble consoles out of component input channels, imaging devices, and multimedia (audio) channels.
The following notes may provide some guidance to those who wish to create new console types (i.e., port the redisplay code to a new platform). They are based on an unsuccessful attempt to refactor the Xft code into a new console type while sharing most routines with the X console. (For clarification or suggestions, feel free to write Stephen Turnbull.)
The first thing to realize is that the naming of many modules obscures their relationship to the console abstraction. For example, the `objects-console-type', `redisplay-console-type', and `glyphs-console-type' series of modules have nothing to do with Lisp objects and little to do with redisplay, respectively. Rather they implement abstractions used for rendering on each console type, such as fonts and colors (`objects') and string and graphics drawing primitives (`redisplay'). These modules are conceptually part of the console implementations, not part of redisplay or Lisp.
Public methods of a console are implemented as C functions declared
static, following a rigid naming convention:
`console-type_method-name'. Methods are bound to the
console type in the `console_type_create_file' functions for
each console component (console, device, and frame) using the
`CONSOLE_HAS_METHOD' family of macros. Methods for displaying
images are bound using the `IIFORMAT_HAS_DEVMETHOD' family of
macros. Methods are invoked using the `CONMETH', `DEVMETH',
and `FRAMEMETH' families of macros, which look up the relevant
methods in the object's table of methods.
N.B. All of the object tables are actually references to console method tables. To create a variant of an existing console, there is a `CONSOLE_INHERITS_METHOD' constructor, but this actually constructs the name of the parent's method pointer and stores in the derived console type's method table. Of course this is time-efficient, and since there are few console types it is a neglible waste of space. However in practice this may have contributed to breaking the various abstractions, and the variant console must be coded in the same file as the parent (because the methods are static). Another minor symptom of the incompleteness of the abstraction is the fact that the API for inheritance of device methods for image formats is named `IIFORMAT_HAS_SHARED_METHOD', although the semantics are identical.
One problem encountered in attempting to create an Xft console type as a derivative of the X console type was that there is no support for such union types in the consistency-checking code, whether for the fundamental Lisp consistency checks (the `CHECK_SOMETHING' family of macros) or for the error-checking variants of many functions. These APIs all simply check for the apparent console type, which is a single symbol (or enumerator).
To create a new console with mostly new methods, it's probably best to copy all of the `function-console-type' files from a similar console (or several, if the new console type seems like a combination of several existing console types), renaming the files by substituting new-console-type for console-type. Then proceed in the obvious way by renaming methods from `console-type_method-name' to `new-console-type_method-name', and implementing them.
Once you've done that, then the fun starts. Insert the initialization functions (`syms_of_file', `vars_of_file', `console_type_create_file', etc.) in `main_1' in `emacs.c'.
Add a device creation function `make-console-type-device' in `device.el'. Add the device type to the calls to `Face-frob-property' in `faces.el', as well as calls to the device initializer functions for devices and frames, and "additional frobbing" in that file.
You may wish to add an option to force the initial frame to that device type to `emacs.c'. Don't forget to document it in the command help function in `startup.el'.
You may need to add support for your console type in `init_event_stream' in `event-stream.c'.
If your console has a different UI for fonts or colors, or adds new capability, you may need to add a `console-type-faces.el' file, or add code to the `parent-type-faces.el' file, to support new font or color capability. Probably initialization code in `faces.c' will be needed too.
A check for the console type is probably needed in `init_redisplay' in `redisplay.c'.
Ditto for the `console-type-init.el' file.
Don't forget that Emacs windows are console-dependent, too. At least a `WINDOW_console-type_P'-checking macro should be added in `window-impl.h'.
Note that this project failed; there are probably many other details to be implemented that I didn't get to. But don't let that stop you!
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
`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, NeXTstep, 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.
`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] | [ ? ] |