Because OpenGL uses visuals to distinguish various frame buffer capabilities, programmers using OpenGL need to be aware of the required steps to create a window with a non-default visual. As mentioned earlier a colormap created for the visual is necessary. But the most irksome thing to remember about creating a window with a non-default visual is that the border pixel value must be specified if the window's visual is not the same as its parent's visual. Otherwise a BadMatch is generated.
Before actually creating the window, the argument to the -geometry option should be parsed using XParseGeometry to obtain the user's requested size and location. The size will be needed when we create the window. Both the size and location are needed to set up the ICCCM size hints for the window manager. A fixed aspect ratio is also requested by setting up the right size hints if the -keepaspect option is specified.
Once the window is created, XSetStandardProperties sets up the various standard ICCCM properties including size hints, icon name, and window name. Then the ICCCM window manager hints are set up to indicate the window's initial state. The -iconic option sets the window manager hints to indicate the window should be initially iconified. XAllocWMHints allocates a hints structure. Once filled in, XSetWMHints sets up the hint property for the window.
The final addition to the window is the WM_PROTOCOLS property which indicates window manager protocols the client understands. The most commonly used protocol defined by ICCCM is WM_DELETE_WINDOW. If this atom is listed in the WM_PROTOCOLS property of a top-level window, then when the user selects the program be quit from the window manager, the window manager will politely send a WM_DELETE_WINDOW message to the client instructing the client to delete the window. If the window is the application's main window, the client is expected to terminate. If this property is not set, the window manager will simply ask the X server to terminate the client's connection without notice to the client. By default, this results in Xlib printing an ugly message like:
X connection to :0.0 broken (explicit kill or server shutdown).Asking to participate in the WM_DELETE_WINDOW protocol allows the client to safely handle requests to quit from the window manager.
The property has another advantage for OpenGL programs. Many
OpenGL programs doing animation will use XPending to check for
pending X events and otherwise draw their animation. But if all a
client's animation is direct OpenGL rendering and the client does not otherwise
do any X requests, the client never sends requests to the X server. Due to
a problem in XPending's
implementation on many Unix operating systems,
such an OpenGL program might not notice its X connection was terminated for
sometime. Using the WM_DELETE_WINDOW protocol eliminates this problem
because the window manager notifies the client via a message (tripping
XPending) and the client is expected to drop the connection.
Using the WM_DELETE_WINDOW protocol is good practice even if you do not use XPending and the Xlib message does not bother you.
All these steps (besides creating a window with a non-default visual) are standard for creating a top-level X window. A top-level window is a window created as a child of the root window (the window manager may choose to reparent the window when it is mapped to add a border). Note that the properties discussed are placed on the top-level window, not necessarily the same window that OpenGL renders into. While glxdino creates a single window, a more complicated program might nest windows used for OpenGL rendering inside the top-level window. The ICCCM window manager properties belong on top-level windows only.
An IRIS GL programmer not familiar with X will probably find these details cumbersome. Most of the work will be done for you if you use a toolkit layered on top of Xlib.
Now a window and an OpenGL rendering context exist. In OpenGL (unlike Xlib), you do not pass the rendering destination into every rendering call. Instead a given OpenGL rendering context is bound to a window using glXMakeCurrent. Once bound, all OpenGL rendering calls operate using the current OpenGL rendering context and the current bound window. A thread can only be bound to one window and one rendering context at a time. A context can only be bound to a single thread at a time. If you call glXMakeCurrent again, it unbinds from the old context and window and then binds to the newly specified context and window. You can unbind a thread from a window and a context by passing NULL for the context and None for the drawable.