Back to index

kdeartwork  4.3.2
space.cpp
Go to the documentation of this file.
00001 /*
00002  *
00003  *            kStart OpenGL screensave for KDE
00004  *
00005  * $Id$
00006  *
00007  *            Copyright (C) 1998 Bernd Johannes Wuebben
00008  *                   wuebben@math.cornell.edu
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this program; if not, write to the Free
00022  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023  *
00024  * Based on star.c:
00025  *
00026  * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
00027  *
00028  * Permission to use, copy, modify, distribute, and sell this software and
00029  * its documentation for any purpose is hereby granted without fee, provided
00030  * that (i) the above copyright notices and this permission notice appear in
00031  * all copies of the software and related documentation, and (ii) the name of
00032  * Silicon Graphics may not be used in any advertising or
00033  * publicity relating to the software without the specific, prior written
00034  * permission of Silicon Graphics.
00035  *
00036  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
00037  * ANY KIND,
00038  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
00039  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00040  *
00041  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
00042  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
00043  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00044  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
00045  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
00046  * OF THIS SOFTWARE.
00047  */
00048 
00049 #define LONG64
00050 //#define QT_CLEAN_NAMESPACE
00051 
00052 #include <qslider.h>
00053 #include <qlayout.h>
00054 //Added by qt3to4:
00055 #include <QVBoxLayout>
00056 #include <QHBoxLayout>
00057 #include <kglobal.h>
00058 #include <kconfig.h>
00059 #include <krandomsequence.h>
00060 #include <kdebug.h>
00061 #include "xlock.h"
00062 #include "helpers.h"
00063 #include <config-xsavers.h> // HAVE_GL
00064 
00065 #ifdef HAVE_GL
00066 
00067 #include <klocale.h>
00068 
00069 #undef index
00070 #include "space.h"
00071 #include <math.h>
00072 #include <X11/Intrinsic.h>
00073 #ifdef HAVE_GL_XMESA_H
00074 #include <GL/xmesa.h>
00075 #endif
00076 #include <GL/gl.h>
00077 #include <GL/glx.h>
00078 #ifdef HAVE_GL_GLUT_H
00079 // We don't need GLUT, but some BROKEN GLU implemenations, such as the one
00080 // used in SuSE Linux 6.3, do. :(
00081 #include <GL/glut.h>
00082 #endif
00083 #include <GL/glu.h>
00084 
00085 #ifndef PI
00086 #ifdef M_PI
00087 #define PI M_PI
00088 #else
00089 #define PI 3.141592657
00090 #endif
00091 #endif
00092 
00093 enum {
00094     NORMAL = 0,
00095     WEIRD = 1
00096 } flag = NORMAL;
00097 
00098 enum {
00099     STREAK = 0,
00100     CIRCLE = 1
00101 };
00102 
00103 #define MAXSTARS 400
00104 #define MAXPOS 10000
00105 #define MAXWARP1 10
00106 #define MAXANGLES 6000
00107 
00108 
00109 typedef struct _starRec {
00110     GLint type;
00111     float x[2], y[2], z[2];
00112     float offsetX, offsetY, offsetR, rotation;
00113 } starRec;
00114 
00115 
00116 GLenum doubleBuffer, directRender;
00117 GLint windW, windH;
00118 
00119 GLint starCount = MAXSTARS / 2;
00120 float speed = 1.0;
00121 float warpinterval = 30000.0;
00122 GLint nitro = 0;
00123 starRec stars[MAXSTARS];
00124 float sinTable[MAXANGLES];
00125 
00126 static GLXContext  glx_context;
00127 static KRandomSequence *rnd = 0;
00128 
00129 float Sin(float angle)
00130 {
00131 
00132     return (sinTable[(GLint)angle]);
00133 }
00134 
00135 float Cos(float angle)
00136 {
00137 
00138     return (sinTable[((GLint)angle+(MAXANGLES/4))%MAXANGLES]);
00139 }
00140 
00141 void NewStar(GLint n, GLint d)
00142 {
00143 
00144     if (rnd->getLong(4) == 0) {
00145        stars[n].type = CIRCLE;
00146     } else {
00147        stars[n].type = STREAK;
00148     }
00149     stars[n].x[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2;
00150     stars[n].y[0] = rnd->getDouble() * MAXPOS - MAXPOS / 2;
00151     stars[n].z[0] = rnd->getDouble() * MAXPOS + d;
00152     if (rnd->getLong(4) == 0 && flag == WEIRD) {
00153        stars[n].offsetX = rnd->getDouble()* 100 - 100 / 2;
00154        stars[n].offsetY = rnd->getDouble()* 100 - 100 / 2;
00155        stars[n].offsetR = rnd->getDouble()* 25 - 25 / 2;
00156     } else {
00157        stars[n].offsetX = 0.0;
00158        stars[n].offsetY = 0.0;
00159        stars[n].offsetR = 0.0;
00160     }
00161 }
00162 
00163 void RotatePoint(float *x, float *y, float rotation)
00164 {
00165     float tmpX, tmpY;
00166 
00167     tmpX = *x * Cos(rotation) - *y * Sin(rotation);
00168     tmpY = *y * Cos(rotation) + *x * Sin(rotation);
00169     *x = tmpX;
00170     *y = tmpY;
00171 }
00172 
00173 void MoveStars(void)
00174 {
00175     float offset;
00176     GLint n;
00177 
00178     offset = speed * 60.0;
00179 
00180     for (n = 0; n < starCount; n++) {
00181        stars[n].x[1] = stars[n].x[0];
00182        stars[n].y[1] = stars[n].y[0];
00183        stars[n].z[1] = stars[n].z[0];
00184        stars[n].x[0] += stars[n].offsetX;
00185        stars[n].y[0] += stars[n].offsetY;
00186        stars[n].z[0] -= offset;
00187         stars[n].rotation += stars[n].offsetR;
00188         if (stars[n].rotation > MAXANGLES) {
00189             stars[n].rotation = 0.0;
00190        }
00191     }
00192 }
00193 
00194 GLenum StarPoint(GLint n)
00195 {
00196     float x0, y0, x1, y1, width;
00197     GLint i;
00198 
00199     x0 = stars[n].x[0] * windW / stars[n].z[0];
00200     y0 = stars[n].y[0] * windH / stars[n].z[0];
00201     RotatePoint(&x0, &y0, stars[n].rotation);
00202     x0 += windW / 2.0;
00203     y0 += windH / 2.0;
00204 
00205     if (x0 >= 0.0 && x0 < windW && y0 >= 0.0 && y0 < windH) {
00206        if (stars[n].type == STREAK) {
00207            x1 = stars[n].x[1] * windW / stars[n].z[1];
00208            y1 = stars[n].y[1] * windH / stars[n].z[1];
00209            RotatePoint(&x1, &y1, stars[n].rotation);
00210            x1 += windW / 2.0;
00211            y1 += windH / 2.0;
00212 
00213            glLineWidth(MAXPOS/100.0/stars[n].z[0]+1.0);
00214            glColor3f((MAXWARP1-speed)/MAXWARP1, (MAXWARP1-speed)/MAXWARP1, .9);
00215            if (fabs(x0-x1) < 1.0 && fabs(y0-y1) < 1.0) {
00216               glBegin(GL_POINTS);
00217                   glVertex2f(x0, y0);
00218               glEnd();
00219            } else {
00220               glBegin(GL_LINES);
00221                   glVertex2f(x0, y0);
00222                   glVertex2f(x1, y1);
00223               glEnd();
00224            }
00225        } else {
00226            width = MAXPOS / 10.0 / stars[n].z[0] + 1.0;
00227            glColor3f(1.0, 0.0, 0.0);
00228            glBegin(GL_POLYGON);
00229               for (i = 0; i < 8; i++) {
00230                   float x = x0 + width * Cos((float)i*MAXANGLES/8.0);
00231                   float y = y0 + width * Sin((float)i*MAXANGLES/8.0);
00232                   glVertex2f(x, y);
00233               };
00234            glEnd();
00235        }
00236        return GL_TRUE;
00237     } else {
00238        return GL_FALSE;
00239     }
00240 }
00241 
00242 void ShowStars(void)
00243 {
00244     GLint n;
00245 
00246     glClear(GL_COLOR_BUFFER_BIT);
00247 
00248     for (n = 0; n < starCount; n++) {
00249        if (stars[n].z[0] > speed || (stars[n].z[0] > 0.0 && speed < MAXWARP1)) {
00250            if (StarPoint(n) == GL_FALSE) {
00251               NewStar(n, MAXPOS);
00252            }
00253        } else {
00254            NewStar(n, MAXPOS);
00255        }
00256     }
00257 }
00258 
00259 static void Init(void)
00260 {
00261     float angle;
00262     GLint n;
00263 
00264     for (n = 0; n < MAXSTARS; n++) {
00265        NewStar(n, 100);
00266     }
00267 
00268     angle = 0.0;
00269     for (n = 0; n < MAXANGLES ; n++) {
00270        sinTable[n] = sin(angle);
00271         angle += PI / (MAXANGLES / 2.0);
00272     }
00273 
00274     glClearColor(0.0, 0.0, 0.0, 0.0);
00275 
00276     glDisable(GL_DITHER);
00277 }
00278 
00279 void reshape(int width, int height)
00280 {
00281 
00282     windW = (GLint)width;
00283     windH = (GLint)height;
00284 
00285     glViewport(0, 0, windW, windH);
00286 
00287     glMatrixMode(GL_PROJECTION);
00288     glLoadIdentity();
00289     gluOrtho2D(-0.5, windW+0.5, -0.5, windH+0.5);
00290     glMatrixMode(GL_MODELVIEW);
00291 
00292 }
00293 
00294 void Idle(void)
00295 {
00296 
00297     MoveStars();
00298     ShowStars();
00299     if (nitro > 0) {
00300        speed = (float)(nitro / 10) + 1.0;
00301        if (speed > MAXWARP1) {
00302            speed = MAXWARP1;
00303        }
00304        if (++nitro > MAXWARP1*10) {
00305            nitro = -nitro;
00306        }
00307     } else if (nitro < 0) {
00308        nitro++;
00309        speed = (float)(-nitro / 10) + 1.0;
00310        if (speed > MAXWARP1) {
00311            speed = MAXWARP1;
00312        }
00313     }
00314 
00315     glFlush();
00316 
00317     /*    if (doubleBuffer) {
00318        tkSwapBuffers();
00319     }*/
00320 }
00321 
00322 
00323 void
00324 drawSpace(Window /*window*/)
00325 {
00326 
00327   /*
00328     Display    *display = dsp;
00329     //glXMakeCurrent(display, window, mp->glx_context);
00330     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00331     glFlush();
00332     glXSwapBuffers(display, window);
00333   */
00334 
00335   Idle();
00336 
00337 }
00338 
00339 
00340 void release_Space(){
00341 
00342   glXDestroyContext(dsp, glx_context);
00343 
00344 }
00345 
00346 static XVisualInfo *glVis[MAXSCREENS];
00347 
00348 int
00349 getVisual(XVisualInfo * wantVis, int visual_count)
00350 {
00351         Display    *display = dsp;
00352         static int  first;
00353        int i;
00354 
00355         if (first) {
00356                 for (screen = 0; screen < MAXSCREENS; screen++)
00357                         glVis[screen] = NULL;
00358         }
00359 
00360         if (!glVis[screen]) {
00361                 if (mono) {
00362                         /* Monochrome display - use color index mode */
00363                         int         attribList[] = {GLX_DOUBLEBUFFER, None};
00364 
00365                         glVis[screen] = glXChooseVisual(display, screen, attribList);
00366                 } else {
00367                         int         attribList[] =
00368                         {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None};
00369 
00370                         glVis[screen] = glXChooseVisual(display, screen, attribList);
00371                 }
00372         }
00373         // Make sure we have a visual
00374         if (!glVis[screen]) {
00375                 return (0);
00376         }
00377 
00378         /* check if GL can render into root window. */
00379        for(i=0;i<visual_count;i++)
00380                 if ( (glVis[screen]->visual == (wantVis+i)->visual) )
00381                         return (1); // success
00382 
00383         // The visual we received did not match one we asked for
00384         return (0);
00385 }
00386 
00387 void
00388 initSpace(Window window)
00389 {
00390        Display    *display = dsp;
00391        XWindowAttributes xwa;
00392 
00393 
00394        (void) XGetWindowAttributes(dsp, window, &xwa);
00395        int         n;
00396        XVisualInfo *wantVis, vTemplate;
00397        int  VisualClassWanted=-1;
00398 
00399        vTemplate.screen = screen;
00400        vTemplate.depth = xwa.depth;
00401 
00402        if (VisualClassWanted == -1) {
00403          vTemplate.c_class = DefaultVisual(display, screen)->c_class;
00404        } else {
00405          vTemplate.c_class = VisualClassWanted;
00406        }
00407 
00408        wantVis = XGetVisualInfo(display,
00409                              VisualScreenMask | VisualDepthMask | VisualClassMask,
00410                              &vTemplate, &n);
00411 
00412        if (VisualClassWanted != -1 && n == 0) {
00413          /* Wanted visual not found so use default */
00414 
00415          vTemplate.c_class = DefaultVisual(display, screen)->c_class;
00416 
00417          wantVis = XGetVisualInfo(display,
00418                                VisualScreenMask | VisualDepthMask | VisualClassMask,
00419                                &vTemplate, &n);
00420        }
00421        /* if User asked for color, try that first, then try mono */
00422        /* if User asked for mono.  Might fail on 16/24 bit displays,
00423           so fall back on color, but keep the mono "look & feel". */
00424 
00425        if (!getVisual(wantVis, n)) {
00426          if (!getVisual(wantVis, n)) {
00427            kError() << i18n("GL can not render with root visual\n") << endl;
00428            return;
00429          }
00430        }
00431 
00432        /* PURIFY 3.0a on SunOS4 reports a 104 byte memory leak on the next line each
00433         * time that morph3d mode is run in random mode. */
00434 
00435        glx_context = glXCreateContext(display, wantVis, 0, True);
00436 
00437        XFree((char *) wantVis);
00438 
00439 
00440        glXMakeCurrent(display, window, glx_context);
00441        glDrawBuffer(GL_FRONT);
00442 
00443        if (mono) {
00444          glIndexi(WhitePixel(display, screen));
00445          glClearIndex(BlackPixel(display, screen));
00446        }
00447 
00448        reshape(xwa.width, xwa.height);
00449        Init();
00450 }
00451 
00452 
00453 
00454 
00455 #endif
00456 
00457 #define MINSPEED 1
00458 #define MAXSPEED 100
00459 #define DEFSPEED 50
00460 #define MINWARP 1
00461 #define MAXWARP 30
00462 #define DEFWARP 2
00463 #define WARPFACTOR 100
00464 //-----------------------------------------------------------------------------
00465 
00466 #include <qpushbutton.h>
00467 #include <qcheckbox.h>
00468 #include <qlabel.h>
00469 #include <qcolor.h>
00470 
00471 #include <kmessagebox.h>
00472 
00473 #include "space.moc"
00474 
00475 #undef Below
00476 
00477 static kSpaceSaver *saver = NULL;
00478 
00479 void startScreenSaver( Drawable d )
00480 {
00481        if ( saver )
00482               return;
00483        saver = new kSpaceSaver( d );
00484 }
00485 
00486 void stopScreenSaver()
00487 {
00488        if ( saver )
00489               delete saver;
00490        saver = NULL;
00491 }
00492 
00493 int setupScreenSaver()
00494 {
00495        kSpaceSetup dlg;
00496 
00497        return dlg.exec();
00498 }
00499 
00500 //-----------------------------------------------------------------------------
00501 
00502 kSpaceSaver::kSpaceSaver( Drawable drawable ) : kScreenSaver( drawable )
00503 {
00504        rnd = new KRandomSequence();
00505        readSettings();
00506        counter = (int)warpinterval *WARPFACTOR;
00507 
00508        initXLock( mGc );
00509        initSpace( mDrawable );
00510 
00511        timer.start( speed );
00512        connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
00513 }
00514 
00515 kSpaceSaver::~kSpaceSaver()
00516 {
00517        timer.stop();
00518        release_Space();
00519        delete rnd; rnd = 0;
00520 }
00521 
00522 void kSpaceSaver::setSpeed( int spd )
00523 {
00524        timer.stop();
00525        speed = MAXSPEED - spd ;
00526        //     printf("speed %d\n",speed);
00527        timer.stop();
00528        timer.start( speed  );
00529 }
00530 
00531 void kSpaceSaver::setWarp( int  w )
00532 {
00533         warpinterval = w;
00534        counter = (int)warpinterval;
00535        initSpace( mDrawable );
00536 }
00537 
00538 void kSpaceSaver::readSettings()
00539 {
00540        KConfig *config = klock_config();
00541        KConfigGroup group = config.group( "Settings" );
00542 
00543        QString str;
00544 
00545        str = group.readEntry( "Speed" );
00546        if ( !str.isNull() )
00547               speed = MAXSPEED - str.toInt();
00548        else
00549               speed = DEFSPEED;
00550 
00551        warpinterval = group.readEntry( "WarpInterval", 15 );
00552        delete config;
00553 }
00554 
00555 void kSpaceSaver::slotTimeout()
00556 {
00557   //printf("%d %d \n",(int)warpinterval, MAXWARP);
00558   if(warpinterval != MAXWARP){
00559      if(nitro == 0)
00560      counter -= speed +1;
00561 
00562      if(counter <= 0){
00563        nitro = 1;
00564        counter = (int) warpinterval *WARPFACTOR;
00565      }
00566   }
00567   else
00568     nitro = 0;
00569 
00570   drawSpace( mDrawable );
00571 }
00572 
00573 //-----------------------------------------------------------------------------
00574 
00575 kSpaceSetup::kSpaceSetup( QWidget *parent, const char *name )
00576        : KDialogBase( parent, name, true, i18n("Setup Space Screen Saver"),
00577                      Ok|Cancel|Help, Ok, true )
00578 {
00579     setButtonText( Help, i18n( "A&bout" ) );
00580     readSettings();
00581 
00582     QWidget *page = new QWidget( this );
00583     setMainWidget( page );
00584     QHBoxLayout *hb = new QHBoxLayout( page, 0, spacingHint() );
00585     QVBoxLayout *vb = new QVBoxLayout( hb, spacingHint() );
00586 
00587     QLabel *label;
00588     QSlider *slider;
00589 
00590     label = new QLabel( i18n("Speed:"), page );
00591     vb->addWidget( label );
00592 
00593     slider = new QSlider(MINSPEED, MAXSPEED, 10, speed, Qt::Horizontal,
00594                   page );
00595     vb->addWidget( slider );
00596     slider->setTickmarks(QSlider::TicksBelow);
00597     slider->setTickInterval(10);
00598     connect( slider, SIGNAL( valueChanged( int ) ), SLOT( slotSpeed( int ) ) );
00599 
00600     label = new QLabel( i18n("Warp interval:"), page );
00601     vb->addWidget( label );
00602 
00603     slider = new QSlider(MINWARP, MAXWARP, 3, warpinterval, Qt::Horizontal, page );
00604     vb->addWidget( slider );
00605     slider->setTickmarks(QSlider::TicksBelow);
00606     slider->setTickInterval(3);
00607     connect( slider, SIGNAL( valueChanged( int ) ), SLOT( slotWarp( int ) ) );
00608 
00609     vb->addStrut( 150 );
00610     vb->addStretch();
00611 
00612     preview = new QWidget( page );
00613     hb->addWidget( preview );
00614     preview->setFixedSize( 220, 170 );
00615     preview->setBackgroundColor( Qt::black );
00616     preview->setAutoFillBackground(true);
00617     preview->show();    // otherwise saver does not get correct size
00618     saver = new kSpaceSaver( preview->winId() );
00619 }
00620 
00621 void kSpaceSetup::readSettings()
00622 {
00623        KConfig *config = klock_config();
00624        KConfigGroup group = config->group( "Settings" );
00625 
00626        speed = group.configEntry( "Speed", speed );
00627 
00628        if ( speed > MAXSPEED )
00629               speed = MAXSPEED;
00630        else if ( speed < MINSPEED )
00631               speed = MINSPEED;
00632 
00633        warpinterval = group.configEntry( "WarpInterval", 15 );
00634 
00635        delete config;
00636 }
00637 
00638 void kSpaceSetup::slotSpeed( int num )
00639 {
00640        speed = num ;
00641 
00642        if ( saver )
00643               saver->setSpeed( speed );
00644 }
00645 
00646 void kSpaceSetup::slotWarp( int num )
00647 {
00648         warpinterval = num;
00649        if ( saver )
00650               saver->setWarp( warpinterval );
00651 }
00652 
00653 void kSpaceSetup::slotOk()
00654 {
00655        KConfig *config = klock_config();
00656        KConfigGroup group = config->group( "Settings" );
00657 
00658        QString sspeed;
00659        sspeed.setNum( speed );
00660        group.writeEntry( "Speed", sspeed );
00661 
00662        QString interval;
00663        interval.setNum( (int)warpinterval );
00664        group.writeEntry( "WarpInterval", interval );
00665 
00666        config->sync();
00667        delete config;
00668        accept();
00669 }
00670 
00671 void kSpaceSetup::slotHelp()
00672 {
00673        KMessageBox::about(this,
00674               i18n("KSpace\nCopyright (c) 1998\n"
00675                                "Bernd Johannes Wuebben <wuebben@kde.org>"));
00676 }
00677 
00678 
00679 /*
00680 static GLenum Args(int argc, char **argv)
00681 {
00682     GLint i;
00683 
00684     doubleBuffer = GL_FALSE;
00685     directRender = GL_TRUE;
00686 
00687     for (i = 1; i < argc; i++) {
00688        if (strcmp(argv[i], "-sb") == 0) {
00689            doubleBuffer = GL_FALSE;
00690        } else if (strcmp(argv[i], "-db") == 0) {
00691            doubleBuffer = GL_TRUE;
00692        } else if (strcmp(argv[i], "-dr") == 0) {
00693            directRender = GL_TRUE;
00694        } else if (strcmp(argv[i], "-ir") == 0) {
00695            directRender = GL_FALSE;
00696        }
00697     }
00698     return GL_TRUE;
00699 }
00700 
00701 
00702 
00703 void main(int argc, char **argv)
00704 {
00705     GLenum type;
00706 
00707     if (Args(argc, argv) == GL_FALSE) {
00708        tkQuit();
00709     }
00710 
00711     windW = 300;
00712     windH = 300;
00713     tkInitPosition(0, 0, 300, 300);
00714 
00715     type = TK_RGB;
00716     type |= (doubleBuffer) ? TK_DOUBLE : TK_SINGLE;
00717     type |= (directRender) ? TK_DIRECT : TK_INDIRECT;
00718     tkInitDisplayMode(type);
00719 
00720     if (tkInitWindow("Stars") == GL_FALSE) {
00721        tkQuit();
00722     }
00723 
00724     Init();
00725 
00726     tkExposeFunc(Reshape);
00727     tkReshapeFunc(Reshape);
00728     tkKeyDownFunc(Key);
00729     tkIdleFunc(Idle);
00730     tkExec();
00731 }
00732 
00733 */