summaryrefslogtreecommitdiff
path: root/src/glw/boilerplate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glw/boilerplate.c')
-rw-r--r--src/glw/boilerplate.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/src/glw/boilerplate.c b/src/glw/boilerplate.c
new file mode 100644
index 0000000000..c53a3fa735
--- /dev/null
+++ b/src/glw/boilerplate.c
@@ -0,0 +1,451 @@
+/*
+
+ BOILERPLATE
+
+ To get started with mixed model programming with Motif and OpenGL, this
+ boilerplate `application' might help get you started.
+
+ This program honors two environment variables:
+
+ SETVISUAL <id> Makes the application use the indicated visual,
+ instead of the one chosen by glxChooseVisual.
+
+ SAMEVISUAL Make the application use the same visual for the
+ GUI as for the 3D GL Widget.
+
+ The basic idea is to minimize colormap `flash' on systems with only one
+ hardware colormap, especially when focus shifts between several
+ of the application's windows, e.g. the about box.
+
+ If you have suggestions for improvements, please mail to:
+
+
+ Jeroen van der Zijp <jvz@cyberia.cfdrc.com>
+
+
+ Feel free to turn this into a useful program!!
+
+*/
+
+
+/*
+
+ This code is hereby placed under GNU GENERAL PUBLIC LICENSE.
+ Copyright (C) 1996 Jeroen van der Zijp <jvz@cyberia.cfdrc.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* Include the kitchen sink */
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <Xm/Xm.h>
+#include <Xm/MainW.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushB.h>
+#include <Xm/CascadeB.h>
+#include <Xm/BulletinB.h>
+#include <Xm/DialogS.h>
+#include <Xm/Frame.h>
+#include <Xm/MessageB.h>
+#include <Xm/Form.h>
+#include <Xm/Separator.h>
+#include <Xm/MwmUtil.h>
+
+/* Now some good stuff */
+#include <GLwMDrawA.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+
+
+/* Stuff */
+Display *display;
+Visual *gui_visual;
+Colormap gui_colormap;
+Colormap gl_colormap;
+XVisualInfo *gl_visualinfo;
+XtAppContext app_context;
+Widget toplevel;
+Widget mainwindow;
+Widget menubar;
+Widget mainform;
+Widget mainframe;
+Widget glwidget;
+Widget button;
+Widget separator;
+GLXContext glx_context;
+
+#ifndef __cplusplus
+#define c_class class
+#endif
+
+/* Requested attributes; fix as you see fit */
+static int glxConfig[]={
+ GLX_RGBA,
+ GLX_DOUBLEBUFFER,
+ GLX_DEPTH_SIZE, 16,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None
+ };
+
+
+/* Forwards */
+static void exposeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void initCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void resizeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void inputCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void byeCB(Widget w,XtPointer client_data,XtPointer call_data);
+static void aboutCB(Widget w,XtPointer client_data,XtPointer call_data);
+static char* showvisualclass(int cls);
+
+
+
+/* Sample application */
+int main(int argc, char *argv[]){
+ char *thevisual;
+ XVisualInfo vi;
+ int nvisinfos,visid,n;
+ Arg args[30];
+ Widget pane,cascade,but;
+
+ /*
+ ** Initialize toolkit
+ ** We do *not* use XtAppInitialize as we want to figure visual and
+ ** colormap BEFORE we create the top level shell!!!
+ */
+ XtToolkitInitialize();
+
+ /* Make application context */
+ app_context=XtCreateApplicationContext();
+
+ /* Try open display */
+ display=XtOpenDisplay(app_context,NULL,"boilerPlate","BoilerPlate",NULL,0,&argc,argv);
+
+ /* Report failure */
+ if(!display){
+ fprintf(stderr,"Unable to open the specified display.\n");
+ fprintf(stderr,"Set your `DISPLAY' environment variable properly or\n");
+ fprintf(stderr,"use the `xhost' command to authorize access to the display.\n");
+ exit(1);
+ }
+
+ /* Check for extension; for Mesa, this is always cool */
+ if(!glXQueryExtension(display,NULL,NULL)){
+ fprintf(stderr,"The specified display does not support the OpenGL extension\n");
+ exit(1);
+ }
+
+ /* Init with default visual and colormap */
+ gui_visual=DefaultVisual(display,0);
+ gui_colormap=DefaultColormap(display,0);
+ gl_colormap=DefaultColormap(display,0);
+
+ /* User insists on a specific visual */
+ if((thevisual=getenv("SETVISUAL"))!=NULL){
+ if(sscanf(thevisual,"%x",&visid)==1){
+ vi.visualid=visid;
+ gl_visualinfo=XGetVisualInfo(display,VisualIDMask,&vi,&nvisinfos);
+ }
+ else{
+ fprintf(stderr,"Please set the `SETVISUAL' variable in hexadecimal\n");
+ fprintf(stderr,"Use one of the Visual ID's reported by `xdpyinfo'\n");
+ exit(1);
+ }
+ }
+
+ /* Find visual the regular way */
+ else{
+ gl_visualinfo=glXChooseVisual(display,DefaultScreen(display),glxConfig);
+ }
+
+ /* Make sure we have a visual */
+ if(!gl_visualinfo){
+ fprintf(stderr,"Unable to obtain visual for graphics\n");
+ exit(1);
+ }
+
+ /* Show what visual is being used */
+ fprintf(stderr,"Using the following visual:\n");
+ fprintf(stderr," visualid: %lx\n",gl_visualinfo->visualid);
+ fprintf(stderr," depth: %d\n",gl_visualinfo->depth);
+ fprintf(stderr," screen: %d\n",gl_visualinfo->screen);
+ fprintf(stderr," bits/rgb: %d\n",gl_visualinfo->bits_per_rgb);
+ fprintf(stderr," class: %s\n",showvisualclass(gl_visualinfo->c_class));
+
+ /*
+ ** If not using default visual, we need a colormap for this visual.
+ ** Yes, the GL widget can allocate one itself, but we want to make
+ ** sure the GUI and the 3D have the same one (if hardware does not
+ ** allow more than one simultaneously).
+ ** This prevents nasty flashing when the window with the 3D widget
+ ** looses the focus.
+ */
+ if(gl_visualinfo->visual!=DefaultVisual(display,0)){
+ fprintf(stderr,"Making another colormap\n");
+ gl_colormap=XCreateColormap(display,
+ RootWindow(display,0),
+ gl_visualinfo->visual,
+ AllocNone);
+ if(!gl_colormap){
+ fprintf(stderr,"Unable to create private colormap\n");
+ exit(1);
+ }
+ }
+
+ /*
+ ** Use common visual for GUI and GL?
+ ** Maybe you can invoke some hardware interrogation function and
+ ** see if more than one hardware map is supported. For the purpose
+ ** of this demo, we'll use an environment variable instead.
+ */
+ if(getenv("SAMEVISUAL")!=NULL){
+ gui_visual=gl_visualinfo->visual;
+ gui_colormap=gl_colormap;
+ }
+
+ fprintf(stderr,"GUI uses visual: %lx\n",XVisualIDFromVisual(gui_visual));
+
+ /* Create application shell, finally */
+ n=0;
+ XtSetArg(args[n],XmNvisual,gui_visual); n++; /* Plug in that visual */
+ XtSetArg(args[n],XmNcolormap,gui_colormap); n++; /* And that colormap */
+ toplevel=XtAppCreateShell("boilerPlate","BoilerPlate",
+ applicationShellWidgetClass,display,args,n);
+
+
+ /* Main window */
+ n=0;
+ mainwindow=XmCreateMainWindow(toplevel,"window",args,n);
+ XtManageChild(mainwindow);
+
+ /* Make a menu */
+ n=0;
+ XtSetArg(args[n],XmNmarginWidth,0); n++;
+ XtSetArg(args[n],XmNmarginHeight,0); n++;
+ menubar=XmCreateMenuBar(mainwindow,"menubar",args,2);
+ XtManageChild(menubar);
+
+ n=0;
+ pane=XmCreatePulldownMenu(menubar,"pane",args,n);
+ n=0;
+ but=XmCreatePushButton(pane,"Open",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Save",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Save As",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Quit",args,n);
+ XtAddCallback(but,XmNactivateCallback,byeCB,(XtPointer)NULL);
+ XtManageChild(but);
+ XtSetArg(args[0],XmNsubMenuId,pane);
+ cascade=XmCreateCascadeButton(menubar,"File",args,1);
+ XtManageChild(cascade);
+
+ n=0;
+ pane=XmCreatePulldownMenu(menubar,"pane",args,n);
+ n=0;
+ but=XmCreatePushButton(pane,"About",args,n);
+ XtAddCallback(but,XmNactivateCallback,aboutCB,(XtPointer)NULL);
+ XtManageChild(but);
+ XtSetArg(args[0],XmNsubMenuId,pane);
+ cascade=XmCreateCascadeButton(menubar,"Help",args,1);
+ XtManageChild(cascade);
+ XtVaSetValues(menubar,XmNmenuHelpWidget,cascade,NULL);
+
+ /* Main window form */
+ n=0;
+ XtSetArg(args[n],XmNmarginWidth,5); n++;
+ XtSetArg(args[n],XmNmarginHeight,5); n++;
+ mainform=XmCreateForm(mainwindow,"mainForm",args,n);
+ XtManageChild(mainform);
+
+ /* Some nice button */
+ n=0;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ button=XmCreatePushButton(mainform,"Bye",args,n);
+ XtAddCallback(button,XmNactivateCallback,byeCB,(XtPointer)NULL);
+ XtManageChild(button);
+
+ n=0;
+ XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
+ XtSetArg(args[n],XmNbottomWidget,button); n++;
+ XtSetArg(args[n],XmNshadowType,XmSHADOW_ETCHED_IN); n++;
+ separator=XmCreateSeparator(mainform,"separator",args,n);
+ XtManageChild(separator);
+
+ /* Main window frame */
+ n = 0;
+ XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNtopAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
+ XtSetArg(args[n],XmNbottomWidget,separator); n++;
+ XtSetArg(args[n],XmNshadowType,XmSHADOW_IN); n++;
+ mainframe = XmCreateFrame(mainform,"mainFrame",args,n);
+ XtManageChild(mainframe);
+
+ /* GL drawing area */
+ n = 0;
+ XtSetArg(args[n],XmNcolormap,gl_colormap); n++;
+ XtSetArg(args[n],GLwNvisualInfo,gl_visualinfo); n++;
+ XtSetArg(args[n],GLwNinstallColormap,True); n++;
+ XtSetArg(args[n],XmNtraversalOn,True); n++;
+ XtSetArg(args[n],XmNwidth,400); n++;
+ XtSetArg(args[n],XmNheight,300); n++;
+ glwidget = GLwCreateMDrawingArea(mainframe,"glWidget",args,n);
+ XtAddCallback(glwidget,GLwNexposeCallback,(XtCallbackProc)exposeCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNresizeCallback,(XtCallbackProc)resizeCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNginitCallback,(XtCallbackProc)initCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNinputCallback,(XtCallbackProc)inputCB,(XtPointer)NULL);
+ XtManageChild(glwidget);
+
+ /* Set into main window */
+ XmMainWindowSetAreas(mainwindow,menubar,NULL,NULL,NULL,mainform);
+ XtRealizeWidget(toplevel);
+
+ /* Loop until were done */
+ XtAppMainLoop(app_context);
+ return 0;
+ }
+
+
+/* Show visual class */
+static char* showvisualclass(int cls){
+ if(cls==TrueColor) return "TrueColor";
+ if(cls==DirectColor) return "DirectColor";
+ if(cls==PseudoColor) return "PseudoColor";
+ if(cls==StaticColor) return "StaticColor";
+ if(cls==GrayScale) return "GrayScale";
+ if(cls==StaticGray) return "StaticGray";
+ return "Unknown";
+ }
+
+
+static void exposeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+
+ glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
+ glMatrixMode(GL_PROJECTION);
+
+ glLoadIdentity();
+ glOrtho(-1.0,1.0,-1.0,1.0,0.0,1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glLoadIdentity();
+
+ glColor3f(1.0,0.0,0.0);
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-1.0,-1.0,0.0);
+ glVertex3f( 1.0, 1.0,0.0);
+ glEnd();
+ glXSwapBuffers(display,XtWindow(glwidget));
+ }
+
+
+/* Initialize widget */
+static void initCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+
+ /* First, create context. We prefer direct rendering */
+ glx_context=glXCreateContext(display,gl_visualinfo,0,TRUE);
+ if(!glx_context){
+ fprintf(stderr,"Unable to create gl context\n");
+ exit(1);
+ }
+
+ /* Make it current */
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+
+ /* Set a viewport */
+ glViewport(0,0,cbs->width,cbs->height);
+
+ /* You might want to do a lot more here ... */
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glClearColor(1.0,1.0,1.0,1.0);
+ glClearDepth(1.0);
+
+
+ }
+
+
+/* Widget changed size, so adjust txform */
+static void resizeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+ glViewport(0,0,cbs->width,cbs->height);
+
+ /* blablabla */
+ }
+
+
+/* Boilerplate event handling */
+static void inputCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ switch(cbs->event->type){
+ case ButtonPress:
+ switch(cbs->event->xbutton.button){
+ case Button1: fprintf(stderr,"Pressed 1\n"); break;
+ case Button2: fprintf(stderr,"Pressed 2\n"); break;
+ case Button3: fprintf(stderr,"Pressed 3\n"); break;
+ }
+ break;
+ case ButtonRelease:
+ switch(cbs->event->xbutton.button){
+ case Button1: fprintf(stderr,"Released 1\n"); break;
+ case Button2: fprintf(stderr,"Released 2\n"); break;
+ case Button3: fprintf(stderr,"Released 3\n"); break;
+ }
+ break;
+ case MotionNotify:
+ fprintf(stderr,"Moved mouse to (%d %d)\n",
+ cbs->event->xbutton.x,
+ cbs->event->xbutton.y);
+ break;
+ }
+ }
+
+
+/* Hasta la vista, baby */
+static void byeCB(Widget w,XtPointer client_data,XtPointer call_data){
+ exit(0);
+ }
+
+
+/* Pop informative panel */
+static void aboutCB(Widget w,XtPointer client_data,XtPointer call_data){
+ Arg args[10];
+ XmString str;
+ Widget box;
+ str=XmStringCreateLtoR("Boilerplate Mixed Model Programming Example\n\n (C) 1996 Jeroen van der Zijp \n\n jvz@cyberia.cfdrc.com",XmSTRING_DEFAULT_CHARSET);
+ XtSetArg(args[0],XmNnoResize,True);
+ XtSetArg(args[1],XmNautoUnmanage,True);
+ XtSetArg(args[2],XmNmessageString,str);
+ XtSetArg(args[3],XmNdefaultPosition,False);
+ box=XmCreateInformationDialog(toplevel,"About Boilerplate",args,4);
+ XtManageChild(box);
+ XtUnmanageChild(XmMessageBoxGetChild(box,XmDIALOG_HELP_BUTTON));
+ XtUnmanageChild(XmMessageBoxGetChild(box,XmDIALOG_CANCEL_BUTTON));
+ XmStringFree(str);
+ }