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

28. Window-System Support

XEmacs defines the concept of a “device type”, which approximately corresponds to a window-system type, and separates out display-related code into device-independent and device-dependent sections. Generally, the device-independent code will go into a generally-named file such as ‘redisplay.c’, while the device-dependent code goes into ‘redisplay-x.c’, ‘redisplay-gtk.c’, ‘redisplay-msw.c’, etc. Device-dependent methods are called using the DEVMETH macro.

The following device types are defined:

X-Windows (x)

This supports rendering through Xlib, widget support through Xt, and event-handling through Xt.

Microsoft Windows (msw)
GTK/Gnome (gtk)
TTY’s (tty)

This is used for TTY connections (e.g. running inside of an xterm or Windows console window).

Stream devices (stream)

This is used for “stream” devices, of which there is only one – the initial stdio device used when XEmacs is running noninteractively.

In addition, there is a pseudo-device-type ‘xlike’, which is used for abstracting X and GTK code that is very similar.


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

28.1 Creating a Window-System Type

Unfortunately, at the present time, only the console abstraction is really 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 desirable 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 negligible 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!


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

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