Fallback resources inside a program are used when a widget is created and the application can't open the class resource file when it calls XtOpenApplication() to open the connection to the X server. (In the code fragment below, the first two resources are specific to Silicon Graphics and give the application a Silicon Graphics look and feel.)
static String fallbackResources[] = { "*useSchemes: all","*sgimode:True", "*glxwidget*width: 300", "*glxwidget*height: 300", "*frame*shadowType: SHADOW_IN", NULL};
Note: Applications should ship with resource files installed in a resource directory (in /usr/lib/X11/app-defaults). If you do install such a file automatically with your application, there is no need to duplicate the resources in your program.
toplevel = XtOpenApplication(&app, "simplest", NULL, 0, &argc, argv,
fallbackResources, applicationShellWidgetClass, NULL, 0);
...
form = XmCreateForm(toplevel, "form", args, n);
XtManageChild(form);
....
frame = XmCreateFrame (form, "frame", args, n);
...
For more information, see the reference pages for XmForm and XmFrame.
n = 0
XSetArg(args[n] GLwNvisualinfo, (XtArgVal)visinfo);
n++;
glw = GLwCreateMDrawingArea(frame, "glwidget", args, n);
glxwidget = XtVaCreateManagedWidget
("glxwidget", glwMDrawingAreaWidgetClass, frame,
GLwNvisualInfo, visinfo, NULL);
Caution: Creating the widget does not actually create the window. An application must wait until after it has realized the widget before performing any OpenGL operations to the window, or use the ginit callback to indicate when the window has been created. Note that unlike most other Motif widgets, the OpenGL widget explicitly sets the visual. Once a visual is set and the widget is realized, the visual can no longer be changed.
The advantage of using a list of resources is that you can override them with the app-defaults file.
Each callback must first be defined and then added to the widget. In some cases, this is quite simple, as, for example, the resize callback from motif/simplest.c:
static void resize(Widget w, XtPointer client_data, XtPointer call) { GLwDrawingAreaCallbackStruct *call_data; call_data = (GLwDrawingAreaCallbackStruct *) call; glViewport(0, 0, call_data->width, call_data->height); }Other cases are slightly more complex, such as the input callback from motif/simplest.c, which exits when the user presses the <Esc> key:
static void input(Widget w, XtPointer client_data, XtPointer call) {
char buffer[31];
KeySym keysym;
XEvent *event = ((GLwDrawingAreaCallbackStruct *)call) ->event;
switch(event->type) {
case KeyRelease:
XLookupString(&event->xkey, buffer, 30, &keysym, NULL);
switch(keysym) {
case XK_Escape :
exit(EXIT_SUCCESS);
break;
default: break;
}
break;
}
}To add callbacks to a widget, use XtAddCallback(); for example:
XtAddCallback(glxwidget, GLwNexposeCallback, expose, NULL); XtAddCallback(glxwidget, GLwNresizeCallback, resize, NULL); XtAddCallback(glxwidget, GLwNinputCallback, input, NULL);Each callback must ensure that the thread is made current with the correct context to the window associated with the widget generating the callback. You can do this by calling either GLwMDrawingAreaMakeCurrent() or glXMakeCurrent().
If you're using only one GLwMDrawingArea, you can call a routine to make the widget "current" just once, after initializing the widget. However, if you're using more than one GLwMDrawingArea or rendering context, you need to make the correct context and the window current for each callback (see "Binding the Context to the Window").
The following callbacks are available:
Use of this callback is not necessary. Anything done in this callback can also be done after the widget hierarchy has been realized. You can use the callback to keep all the OpenGL code together, keeping the initialization in the same file as the widget creation rather than with widget realization.
If you create a GLwDrawingArea widget as a child of an already realized widget, it's not possible to add the ginit callback before the widget is realized because the widget is immediately realized at creation. In that case, you should initialize immediately after creating the widget.
Note: An application should not perform any OpenGL drawing until it receives an expose callback, although it may set the OpenGL state; for example, it may create display lists and so on.
The input callback is a programming convenience; it provides a convenient way to catch all input events. You can often create a more modular program, however, by providing specific actions and translations in the application rather than using a single catchall callback. See "Input Handling With Widgets and Xt" for more information.