home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src-glut / win32_util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  23.5 KB  |  772 lines

  1.  
  2. /* Copyright (c) Nate Robins, 1997. */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8.  
  9. #include "glutint.h"
  10. #include "glutstroke.h"
  11. #include "glutbitmap.h"
  12.  
  13. #if defined(__CYGWIN32__)
  14. typedef MINMAXINFO* LPMINMAXINFO;
  15. #else
  16. #include <sys/timeb.h>
  17. #endif
  18.  
  19. extern StrokeFontRec glutStrokeRoman, glutStrokeMonoRoman;
  20. extern BitmapFontRec glutBitmap8By13, glutBitmap9By15, glutBitmapTimesRoman10, glutBitmapTimesRoman24, glutBitmapHelvetica10, glutBitmapHelvetica12, glutBitmapHelvetica18;
  21.  
  22. int
  23. gettimeofday(struct timeval* tp, void* tzp)
  24. {
  25. #if defined(__CYGWIN32__)
  26.   /* gettimeofday() is not to be implemented in cygwin.dll beta 18 (cf. _syslist.h) */
  27.   /* we use GetTickCount() = number of milliseconds since windoze was started       */
  28.   /* /Stephane Rehel, Nov.16.1997                                                   */
  29.   long tc= GetTickCount();
  30.   tp->tv_sec= tc / 1000L;
  31.   tp->tv_sec= (tc % 1000L) * 1000L;
  32. #else
  33.   struct timeb tb;
  34.  
  35.   ftime(&tb);
  36.   tp->tv_sec = tb.time;
  37.   tp->tv_usec = tb.millitm * 1000;
  38. #endif
  39.  
  40.   /* 0 indicates that the call succeeded. */
  41.   return 0;
  42. }
  43.  
  44. void*
  45. __glutFont(void *font)
  46. {
  47.   switch((int)font) {
  48.   case (int)GLUT_STROKE_ROMAN:
  49.     return &glutStrokeRoman;
  50.   case (int)GLUT_STROKE_MONO_ROMAN:
  51.     return &glutStrokeMonoRoman;
  52.   case (int)GLUT_BITMAP_9_BY_15:
  53.     return &glutBitmap9By15;
  54.   case (int)GLUT_BITMAP_8_BY_13:
  55.     return &glutBitmap8By13;
  56.   case (int)GLUT_BITMAP_TIMES_ROMAN_10:
  57.     return &glutBitmapTimesRoman10;
  58.   case (int)GLUT_BITMAP_TIMES_ROMAN_24:
  59.     return &glutBitmapTimesRoman24;
  60.   case (int)GLUT_BITMAP_HELVETICA_10:
  61.     return &glutBitmapHelvetica10;
  62.   case (int)GLUT_BITMAP_HELVETICA_12:
  63.     return &glutBitmapHelvetica12;
  64.   case (int)GLUT_BITMAP_HELVETICA_18:
  65.     return &glutBitmapHelvetica18;
  66.   }
  67. }
  68.  
  69. int
  70. __glutGetTransparentPixel(Display * dpy, XVisualInfo * vinfo)
  71. {
  72.   /* the transparent pixel on Win32 is always index number 0.  So if
  73.      we put this routine in this file, we can avoid compiling the
  74.      whole of layerutil.c which is where this routine normally comes
  75.      from. */
  76.   return 0;
  77. }
  78.  
  79. void
  80. __glutAdjustCoords(Window parent, int* x, int* y, int* width, int* height)
  81. {
  82.   RECT rect;
  83.  
  84.   /* adjust the window rectangle because Win32 thinks that the x, y,
  85.      width & height are the WHOLE window (including decorations),
  86.      whereas GLUT treats the x, y, width & height as only the CLIENT
  87.      area of the window. */
  88.   rect.left = *x; rect.top = *y;
  89.   rect.right = *x + *width; rect.bottom = *y + *height;
  90.  
  91.   /* must adjust the coordinates according to the correct style
  92.      because depending on the style, there may or may not be
  93.      borders. */
  94.   AdjustWindowRect(&rect, WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
  95.            (parent ? WS_CHILD : WS_OVERLAPPEDWINDOW),
  96.            FALSE);
  97.   /* FALSE in the third parameter = window has no menu bar */
  98.  
  99.   /* readjust if the x and y are offscreen */
  100.   if(rect.left < 0) 
  101.     *x = 0;
  102.   else
  103.     *x = rect.left;
  104.   
  105.   if(rect.top < 0)  
  106.     *y = 0;
  107.   else
  108.     *y = rect.top;
  109.  
  110.   *width = rect.right - rect.left;    /* adjusted width */
  111.   *height = rect.bottom - rect.top;    /* adjusted height */
  112. }
  113.  
  114. extern unsigned __glutMenuButton;
  115. extern GLUTidleCB __glutIdleFunc;
  116. extern GLUTtimer *__glutTimerList;
  117. extern void handleTimeouts(void);
  118. extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, int unique);
  119. static HMENU __glutHMenu;
  120.  
  121. LONG WINAPI __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  122.   POINT         point;            // point structure
  123.   PAINTSTRUCT   ps;            // paint structure
  124.   LPMINMAXINFO  minmax;            // minimum/maximum info structure
  125.   GLUTwindow*   window;            // glut window associated with message
  126.   GLUTmenu*     menu;            // glut menu associated with message
  127.   int x, y, width, height, key;
  128.   int button = -1;
  129.  
  130.   //  printf("__glutWindowProc(0x%x, 0x%x, 0x%x, 0x%x)\n", hwnd, msg, wParam, lParam);
  131.  
  132.   switch(msg) {
  133.   case WM_CREATE:
  134.     return 0;
  135.  
  136.   case WM_CLOSE:
  137.     PostQuitMessage(0);
  138.     return 0;
  139.  
  140.   case WM_DESTROY:
  141.     // TODO: need to add this.
  142.     //    purgeStaleWindow(hwnd);
  143.     return 0;
  144.  
  145.   case WM_PAINT:
  146. //    printf("WM_PAINT\n");
  147.     window = __glutGetWindow(hwnd);
  148.     if (window) {
  149.       BeginPaint(hwnd, &ps);        // must have this for some Win32 reason
  150. #if TAKE_THIS_OUT
  151.       if (window->colormap) {
  152.     SelectPalette(window->hdc, window->colormap->cmap, FORCE_FOREGROUND);
  153.     RealizePalette(window->hdc);           // remap the custom palette
  154.       }
  155. #endif
  156.       EndPaint(hwnd, &ps);
  157.       if (window->win == hwnd) {
  158.     __glutPostRedisplay(window, GLUT_REPAIR_WORK);
  159.       } else if (window->overlay && window->overlay->win == hwnd) {
  160.     __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
  161.       }
  162.     }
  163.     return 0;
  164.  
  165.   case WM_SYSCHAR:
  166.   case WM_CHAR:
  167.     window = __glutGetWindow(hwnd);
  168.     if (!window) {
  169.       break;
  170.     }
  171.     /* Win32 is dumb and sends these messages only to the parent
  172.        window.  Therefore, find out if we're in a child window and
  173.        call the child windows keyboard callback if we are. */
  174.     if (window->parent) {
  175.     GetCursorPos(&point);
  176.     ScreenToClient(hwnd, &point);
  177.     hwnd = ChildWindowFromPoint(hwnd, point);
  178.     window = __glutGetWindow(hwnd);
  179.     }
  180.     if (window->keyboard) {
  181.       GetCursorPos(&point);
  182.       ScreenToClient(window->win, &point);
  183.       __glutSetWindow(window);
  184.       __glutModifierMask = 0;
  185.       if (GetKeyState(VK_SHIFT) < 0)    /* < 0 = high order bit is on */
  186.     __glutModifierMask |= ShiftMask;
  187.       if (GetKeyState(VK_CONTROL) < 0)
  188.     __glutModifierMask |= ControlMask;
  189.       if (GetKeyState(VK_MENU) < 0)
  190.     __glutModifierMask |= Mod1Mask;
  191.       window->keyboard((char)wParam, point.x, point.y);
  192.       __glutModifierMask = (unsigned int) ~0;
  193.     }
  194.     return 0;
  195.  
  196.   case WM_SYSKEYDOWN:
  197.   case WM_KEYDOWN:
  198.     window = __glutGetWindow(hwnd);
  199.     if (!window) {
  200.       break;
  201.     }
  202.     /* Win32 is dumb and sends these messages only to the parent
  203.        window.  Therefore, find out if we're in a child window and
  204.        call the child windows keyboard callback if we are. */
  205.     if (window->parent) {
  206.     GetCursorPos(&point);
  207.     ScreenToClient(hwnd, &point);
  208.     hwnd = ChildWindowFromPoint(hwnd, point);
  209.     window = __glutGetWindow(hwnd);
  210.     }
  211.     if (window->special) {
  212.       switch (wParam) {
  213.     /* *INDENT-OFF* */
  214.     /* function keys */
  215.     case VK_F1:     key = GLUT_KEY_F1; break;
  216.     case VK_F2:     key = GLUT_KEY_F2; break;
  217.     case VK_F3:     key = GLUT_KEY_F3; break;
  218.     case VK_F4:     key = GLUT_KEY_F4; break;
  219.     case VK_F5:     key = GLUT_KEY_F5; break;
  220.     case VK_F6:     key = GLUT_KEY_F6; break;
  221.     case VK_F7:     key = GLUT_KEY_F7; break;
  222.     case VK_F8:     key = GLUT_KEY_F8; break;
  223.     case VK_F9:     key = GLUT_KEY_F9; break;
  224.     case VK_F10:    key = GLUT_KEY_F10; break;
  225.     case VK_F11:    key = GLUT_KEY_F11; break;
  226.     case VK_F12:    key = GLUT_KEY_F12; break;
  227.     /* directional keys */
  228.     case VK_LEFT:   key = GLUT_KEY_LEFT; break;
  229.     case VK_UP:     key = GLUT_KEY_UP; break;
  230.     case VK_RIGHT:  key = GLUT_KEY_RIGHT; break;
  231.     case VK_DOWN:   key = GLUT_KEY_DOWN; break;
  232.     /* *INDENT-ON* */
  233.  
  234.     case VK_PRIOR:
  235.       /* VK_PRIOR is Win32's Page Up */
  236.       key = GLUT_KEY_PAGE_UP;
  237.       break;
  238.     case VK_NEXT:
  239.       /* VK_NEXT is Win32's Page Down */
  240.       key = GLUT_KEY_PAGE_DOWN;
  241.       break;
  242.     case VK_HOME:
  243.       key = GLUT_KEY_HOME;
  244.       break;
  245.     case VK_END:
  246.       key = GLUT_KEY_END;
  247.       break;
  248.     case VK_INSERT:
  249.       key = GLUT_KEY_INSERT;
  250.       break;
  251.     default:
  252.       goto defproc;
  253.       }
  254.       GetCursorPos(&point);
  255.       ScreenToClient(window->win, &point);
  256.       __glutSetWindow(window);
  257.       __glutModifierMask = 0;
  258.       if (GetKeyState(VK_SHIFT) < 0)    // < 0 = high order bit is on
  259.     __glutModifierMask |= ShiftMask;
  260.       if (GetKeyState(VK_CONTROL) < 0)
  261.     __glutModifierMask |= ControlMask;
  262.       if (GetKeyState(VK_MENU) < 0)
  263.     __glutModifierMask |= Mod1Mask;
  264.       window->special(key, point.x, point.y);
  265.       __glutModifierMask = (unsigned int) ~0;
  266.     }
  267.     return 0;
  268.  
  269.   case WM_LBUTTONDOWN:
  270.     button = GLUT_LEFT_BUTTON;
  271.   case WM_MBUTTONDOWN:
  272.     if (button < 0)
  273.       button = GLUT_MIDDLE_BUTTON;
  274.   case WM_RBUTTONDOWN:
  275.     if (button < 0)
  276.       button = GLUT_RIGHT_BUTTON;
  277.     
  278.     /* finish the menu if we get a button down message (user must have
  279.        cancelled the menu). */
  280.     if (__glutMappedMenu) {
  281.       /* TODO: take this out once the menu on middle mouse stuff works
  282.      properly. */
  283.       if (button == GLUT_MIDDLE_BUTTON)
  284.     return 0;
  285.       GetCursorPos(&point);
  286.       ScreenToClient(hwnd, &point);
  287.       __glutItemSelected = NULL;
  288.       __glutFinishMenu(hwnd, point.x, point.y);
  289.       return 0;
  290.     }
  291.  
  292.     /* set the capture so we can get mouse events outside the window */
  293.     SetCapture(hwnd);
  294.  
  295.     /* Win32 doesn't return the same numbers as X does when the mouse
  296.        goes beyond the upper or left side of the window.  roll the
  297.        Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
  298.     x = LOWORD(lParam);
  299.     y = HIWORD(lParam);
  300.     if(x & 1 << 15) x -= (1 << 16);
  301.     if(y & 1 << 15) y -= (1 << 16);
  302.     
  303.     window = __glutGetWindow(hwnd);
  304.     if (window) {
  305.       menu = __glutGetMenuByNum(window->menu[button]);
  306.       if (menu) {
  307.     point.x = LOWORD(lParam); point.y = HIWORD(lParam);
  308.     ClientToScreen(window->win, &point);
  309.     __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
  310.                            button == GLUT_LEFT_BUTTON  ? TPM_LEFTBUTTON :
  311.                            0x0001;
  312.     __glutStartMenu(menu, window, point.x, point.y, x, y);
  313.       } else if (window->mouse) {
  314.     
  315.         __glutSetWindow(window);
  316.     __glutModifierMask = 0;
  317.     if (GetKeyState(VK_SHIFT) < 0)    // < 0 = high order bit is on
  318.       __glutModifierMask |= ShiftMask;
  319.     if (GetKeyState(VK_CONTROL) < 0)
  320.       __glutModifierMask |= ControlMask;
  321.     if (GetKeyState(VK_MENU) < 0)
  322.       __glutModifierMask |= Mod1Mask;
  323.     window->mouse(button, GLUT_DOWN, x, y);
  324.     __glutModifierMask = (unsigned int)~0;
  325.       } else {
  326.     /* Stray mouse events.  Ignore. */
  327.       }
  328.     }
  329.     return 0;
  330.  
  331.   case WM_LBUTTONUP:
  332.     button = GLUT_LEFT_BUTTON;
  333.   case WM_MBUTTONUP:
  334.     if (button < 0)
  335.       button = GLUT_MIDDLE_BUTTON;
  336.   case WM_RBUTTONUP:
  337.     if (button < 0)
  338.       button = GLUT_RIGHT_BUTTON;
  339.  
  340.     /* bail out if we're processing a menu */
  341.     if (__glutMappedMenu) {
  342.       GetCursorPos(&point);
  343.       ScreenToClient(hwnd, &point);
  344.       /* if we're getting the middle button up signal, then something
  345.      on the menu was selected. */
  346.       if (button == GLUT_MIDDLE_BUTTON) {
  347.     return 0;
  348.     /* For some reason, the code below always returns -1 even
  349.      though the point IS IN THE ITEM!  Therefore, just bail out if
  350.      we get a middle mouse up.  The user must select using the
  351.      left mouse button.  Stupid Win32. */
  352. #if 0
  353.      int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
  354.      printf("item = %d %d %d\n", item, point.x, point.y);
  355.      if (item != -1)
  356.        __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
  357.      else
  358.        __glutItemSelected = NULL;
  359.      __glutFinishMenu(hwnd, point.x, point.y);
  360. #endif
  361.       } else {
  362.     __glutItemSelected = NULL;
  363.     __glutFinishMenu(hwnd, point.x, point.y);
  364.       }
  365.       return 0;
  366.     }
  367.  
  368.     /* release the mouse capture */
  369.     ReleaseCapture();
  370.  
  371.     window = __glutGetWindow(hwnd);
  372.     if (window && window->mouse) {
  373.       /* Win32 doesn't return the same numbers as X does when the
  374.      mouse goes beyond the upper or left side of the window.  roll
  375.      the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
  376.       x = LOWORD(lParam);
  377.       y = HIWORD(lParam);
  378.       if(x & 1 << 15) x -= (1 << 16);
  379.       if(y & 1 << 15) y -= (1 << 16);
  380.       
  381.       __glutSetWindow(window);
  382.       __glutModifierMask = 0;
  383.       if (GetKeyState(VK_SHIFT) < 0)    /* < 0 = high order bit is on */
  384.     __glutModifierMask |= ShiftMask;
  385.       if (GetKeyState(VK_CONTROL) < 0)
  386.     __glutModifierMask |= ControlMask;
  387.       if (GetKeyState(VK_MENU) < 0)
  388.     __glutModifierMask |= Mod1Mask;
  389.       window->mouse(button, GLUT_UP, x, y);
  390.       __glutModifierMask = (unsigned int)~0;
  391.     } else {
  392.       /* Window might have been destroyed and all the 
  393.      events for the window may not yet be received. */
  394.     }
  395.     return 0;
  396.  
  397.   case WM_ENTERMENULOOP:
  398.     /* KLUDGE: create a timer that fires every 100 ms when we start a
  399.        menu so that we can still process the idle & timer events (that
  400.        way, the timers will fire during a menu pick and so will the
  401.        idle func. */
  402.     SetTimer(hwnd, 1, 1, NULL);
  403.     return 0;
  404.  
  405.   case WM_TIMER:
  406. //     /* if the timer id is 2, then this is the timer that is set up in
  407. //        the main glut message processing loop, and we don't want to do
  408. //        anything but acknowledge that we got it.  It is used to prevent
  409. //        CPU spiking when an idle function is installed. */
  410. //     if (wParam == 2)
  411. //       return 0;
  412.  
  413.     /* only worry about the idle function and the timeouts, since
  414.        these are the only events we expect to process during
  415.        processing of a menu. */
  416.     /* we no longer process the idle functions (as outlined in the
  417.        README), since drawing can't be done until the menu has
  418.        finished...it's pretty lame when the animation goes on, but
  419.        doesn't update, so you get this weird jerkiness. */
  420. #if 0    
  421.      if (__glutIdleFunc)
  422.        __glutIdleFunc();
  423. #endif
  424.     if (__glutTimerList)
  425.       handleTimeouts();
  426.     return 0;
  427.  
  428.   case WM_EXITMENULOOP:
  429.     /* nuke the above created timer...we don't need it anymore, since
  430.        the menu is gone now. */
  431.     KillTimer(hwnd, 1);
  432.     return 0;
  433.  
  434.   case WM_MENUSELECT:
  435.     if (lParam != 0)
  436.       __glutHMenu = (HMENU)lParam;
  437.     return 0;
  438.  
  439.   case WM_COMMAND:
  440.     if (__glutMappedMenu) {
  441.       if (GetSubMenu(__glutHMenu, LOWORD(wParam)))
  442.     __glutItemSelected = NULL;
  443.       else
  444.     __glutItemSelected = 
  445.       __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));
  446.       GetCursorPos(&point);
  447.       ScreenToClient(hwnd, &point);
  448.       __glutFinishMenu(hwnd, point.x, point.y);
  449.     } 
  450.     return 0;
  451.  
  452.   case WM_MOUSEMOVE:
  453.     //    printf("WM_MOUSEMOVE\n");
  454.     if (!__glutMappedMenu) {
  455.       window = __glutGetWindow(hwnd);
  456.       if (window) {
  457.           /* If motion function registered _and_ buttons held *
  458.              down, call motion function...  */
  459.     x = LOWORD(lParam);
  460.     y = HIWORD(lParam);
  461.  
  462.     /* Win32 doesn't return the same numbers as X does when the
  463.        mouse goes beyond the upper or left side of the window.
  464.        roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */
  465.     if(x & 1 << 15) x -= (1 << 16);
  466.     if(y & 1 << 15) y -= (1 << 16);
  467.  
  468.     if (window->motion && wParam &
  469.             (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
  470.       __glutSetWindow(window);
  471.       window->motion(x, y);
  472.     }
  473.     /* If passive motion function registered _and_
  474.        buttons not held down, call passive motion
  475.        function...  */
  476.     else if (window->passive &&
  477.          ((wParam &
  478.            (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==
  479.           0)) {
  480.       __glutSetWindow(window);
  481.       window->passive(x, y);
  482.     }
  483.       }
  484.     } else {
  485.       /* Motion events are thrown away when a pop up menu is
  486.      active. */
  487.     }
  488.     return 0;
  489.  
  490.   case WM_GETMINMAXINFO:
  491.     /* this voodoo is brought to you by Win32 (again).  It allows the
  492.        window to be bigger than the screen, and smaller than 100x100
  493.        (although it doesn't seem to help the y minimum). */
  494.     minmax = (LPMINMAXINFO)lParam;
  495.     minmax->ptMaxSize.x = __glutScreenWidth;
  496.     minmax->ptMaxSize.y = __glutScreenHeight;
  497.     minmax->ptMinTrackSize.x = 0;
  498.     minmax->ptMinTrackSize.y = 0;
  499.     minmax->ptMaxTrackSize.x = __glutScreenWidth + 
  500.       GetSystemMetrics(SM_CXSIZE) * 2;
  501.     minmax->ptMaxTrackSize.y = __glutScreenHeight + 
  502.       GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
  503.     return 0;
  504.  
  505.   case WM_SIZE:
  506.     window = __glutGetWindow(hwnd);
  507.     if (window) {
  508.       if (window->win != hwnd) {
  509.     /* Ignore ConfigureNotify sent to the overlay planes.
  510.        GLUT could get here because overlays select for
  511.        StructureNotify events to receive DestroyNotify. */
  512.     break;
  513.       }
  514.       width = LOWORD(lParam);
  515.       height = HIWORD(lParam);
  516.       if (width != window->width || height != window->height) {
  517. #if 0
  518.      if (window->overlay) {
  519.        XResizeWindow(__glutDisplay, window->overlay->win, width, height);
  520.      }
  521. #endif
  522.     window->width = width;
  523.     window->height = height;
  524.     __glutSetWindow(window);
  525.     /* Do not execute OpenGL out of sequence with respect
  526.        to the SetWindowPos request! */
  527.     GdiFlush();
  528.     window->reshape(width, height);
  529.     window->forceReshape = FALSE;
  530.     /* A reshape should be considered like posting a
  531.        redisplay; this is necessary for the "Mesa
  532.        glXSwapBuffers to repair damage" hack to operate
  533.        correctly.  Without it, there's not an initial
  534.        back buffer render from which to blit from when
  535.        damage happens to the window. */
  536.     __glutPostRedisplay(window, GLUT_REDISPLAY_WORK);
  537.       }
  538.     }
  539.     return 0;
  540.  
  541.   case WM_SETCURSOR:
  542.     /* if the cursor is not in the client area, then we want to send
  543.        this message to the default window procedure ('cause its
  544.        probably in the border or title, and we don't handle that
  545.        cursor.  otherwise, set our cursor.  Win32 makes us set the
  546.        cursor every time the mouse moves (DUMB!). */
  547.     if(LOWORD(lParam) != HTCLIENT)
  548.       goto defproc;
  549.     window = __glutGetWindow(hwnd);
  550.     if (window) {
  551.       /* since Win32 allows the parent to control a child windows
  552.      cursor, if the cursor is in a child of this window, bail
  553.      out. */
  554.       GetCursorPos(&point);
  555.       ScreenToClient(hwnd, &point);
  556.       if (hwnd != ChildWindowFromPoint(hwnd, point))
  557.     break;
  558.       /* KLUDGE: should actually call __glutSetWindow here, but since
  559.          it does a glXMakeCurrent(), I'm going to avoid doing that and
  560.          simply set the current window instead. */
  561.       /* __glutSetWindow(window); */
  562.       __glutCurrentWindow = window;
  563.       glutSetCursor(window->cursor);
  564.     }
  565.     /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
  566.        DefaultAction section. */
  567.     return 1;
  568.  
  569.   case WM_SETFOCUS:
  570.     window = __glutGetWindow(hwnd);
  571.     if (window) {
  572.       if (window->entry) {
  573.     window->entryState = WM_SETFOCUS;
  574.     __glutSetWindow(window);
  575.     window->entry(GLUT_ENTERED);
  576. //           if (event.type == EnterNotify) {
  577.  
  578. //             /* With overlays established, X can report two
  579. //                enter events for both the overlay and normal
  580. //                plane window. Do not generate a second enter
  581. //                callback if we reported one without an
  582. //                intervening leave. */
  583.  
  584. //             if (window->entryState != EnterNotify) {
  585. //               int num = window->num;
  586. //               Window xid = window->win;
  587.  
  588. //               window->entryState = EnterNotify;
  589. //               __glutSetWindow(window);
  590. //               window->entry(GLUT_ENTERED);
  591.  
  592. //               if (__glutMappedMenu) {
  593.  
  594. //                 /* Do not generate any passive motion events
  595. //                    when menus are in use. */
  596.  
  597. //               } else {
  598.  
  599. //                 /* An EnterNotify event can result in a
  600. //                    "compound" callback if a passive motion
  601. //                    callback is also registered. In this case,
  602. //                    be a little paranoid about the possibility
  603. //                    the window could have been destroyed in the
  604. //                    entry callback. */
  605.  
  606. //                 window = __glutWindowList[num];
  607. //                 if (window && window->passive && window->win == xid) {
  608. //                   __glutSetWindow(window);
  609. //                   window->passive(event.xcrossing.x, event.xcrossing.y);
  610. //                 }
  611. //               }
  612. //             }
  613. //           } else {
  614. //             if (window->entryState != LeaveNotify) {
  615.  
  616. //               /* When an overlay is established for a window
  617. //                  already mapped and with the pointer in it, the
  618. //                  X server will generate a leave/enter event pair
  619. //                  as the pointer leaves (without moving) from the
  620. //                  normal plane X window to the newly mapped
  621. //                  overlay  X window (or vice versa). This
  622. //                  enter/leave pair should not be reported to the
  623. //                  GLUT program since the pair is a consequence of
  624. //                  creating (or destroying) the overlay, not an
  625. //                  actual leave from the GLUT window. */
  626.  
  627. //               if (XEventsQueued(__glutDisplay, QueuedAfterReading)) {
  628. //                 XPeekEvent(__glutDisplay, &ahead);
  629. //                 if (ahead.type == EnterNotify &&
  630. //                   __glutGetWindow(ahead.xcrossing.window) == window) {
  631. //                   XNextEvent(__glutDisplay, &event);
  632. //                   break;
  633. //                 }
  634. //               }
  635. //               window->entryState = LeaveNotify;
  636. //               __glutSetWindow(window);
  637. //               window->entry(GLUT_LEFT);
  638. //             }
  639. //           }
  640. //         } else if (window->passive) {
  641. //           __glutSetWindow(window);
  642. //           window->passive(event.xcrossing.x, event.xcrossing.y);
  643.       }
  644.     }
  645.     return 0;
  646.  
  647.   case WM_KILLFOCUS:
  648.     window = __glutGetWindow(hwnd);
  649.     if (window) {
  650.       if (window->entry) {
  651.     window->entryState = WM_KILLFOCUS;
  652.     __glutSetWindow(window);
  653.     window->entry(GLUT_LEFT);
  654.       }
  655.     }
  656.     return 0;
  657.  
  658.   case WM_ACTIVATE:
  659.     window = __glutGetWindow(hwnd);
  660.     /* make sure we re-select the correct palette if needed */
  661.     if (LOWORD(wParam)) {
  662.       PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
  663.     }
  664.     if (window) {
  665.       GLUTwindow* child;
  666.       int visState;
  667.       visState = !IsIconic(window->win);
  668.       if (visState) {            // not iconic
  669.     visState = IsWindowVisible(window->win);
  670.       }
  671.       if (visState != window->visState) {
  672.     if (window->windowStatus) {
  673.       window->visState = visState;
  674.       __glutSetWindow(window);
  675.       window->windowStatus(visState);
  676.       //      window->visibility(visState ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
  677.     }
  678.     // since Win32 only sends an activate for the toplevel window,
  679.     // update the visibility for all the child windows
  680.     child = window->children;
  681.     while (child) {
  682.       child->visState = visState;
  683.       if (child->windowStatus) {
  684.         child->visState = visState;
  685.         __glutSetWindow(child);
  686.         child->windowStatus(visState);
  687.         //        child->visibility(visState ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
  688.       }
  689.       child = child->siblings;
  690.     }
  691.       }
  692.     }
  693.     return 0;
  694.  
  695.   /* Colour Palette Management */
  696.   case WM_PALETTECHANGED:
  697.     if (hwnd == (HWND)wParam)  /* don't respond to the message that we sent! */
  698.       break;
  699.     /* fall through to WM_QUERYNEWPALETTE */
  700.  
  701.   case WM_QUERYNEWPALETTE:
  702.     window = __glutGetWindow(hwnd);
  703.     if (window && window->colormap) {
  704.       UnrealizeObject(window->colormap->cmap);
  705.       SelectPalette(window->hdc, window->colormap->cmap, FALSE);
  706.       RealizePalette(window->hdc);
  707.       return TRUE;
  708.     }
  709.     return FALSE;
  710.  
  711.   /* miscellaneous messages (don't really need to enumerate them,
  712.      but it's good to know what you're not getting sometimes.) */
  713.   case WM_NCHITTEST:
  714.     /* this event is generated by every mouse move event. */
  715.     goto defproc;
  716.   case WM_NCMOUSEMOVE:
  717.     goto defproc;
  718.   case WM_NCACTIVATE:
  719.     goto defproc;
  720.   case WM_NCPAINT:
  721.     goto defproc;
  722.   case WM_NCCALCSIZE:
  723.     goto defproc;
  724.   case WM_NCCREATE:
  725.     goto defproc;
  726.   case WM_NCDESTROY:
  727.     goto defproc;
  728.   case WM_NCLBUTTONDOWN:
  729.     goto defproc;
  730.   case WM_SETTEXT:
  731.     goto defproc;
  732.   case WM_GETTEXT:
  733.     goto defproc;
  734.   case WM_ACTIVATEAPP:
  735.     goto defproc;
  736.   case WM_GETICON:
  737.     goto defproc;
  738.   case WM_ERASEBKGND:
  739.     goto defproc;
  740.   case WM_WINDOWPOSCHANGING:
  741.     goto defproc;
  742.   case WM_WINDOWPOSCHANGED:
  743.     goto defproc;
  744.   case WM_MOUSEACTIVATE:
  745.     goto defproc;
  746.   case WM_SHOWWINDOW:
  747.     goto defproc;
  748.   case WM_MOVING:
  749.     goto defproc;
  750.   case WM_MOVE:
  751.     goto defproc;
  752.   case WM_KEYUP:
  753.     goto defproc;
  754.   case WM_CAPTURECHANGED:
  755.     goto defproc;
  756.   case WM_SYSCOMMAND:
  757.     goto defproc;
  758.   case WM_ENTERSIZEMOVE:
  759.     goto defproc;
  760.   case WM_ENTERIDLE:
  761.     goto defproc;
  762.  
  763.   default: 
  764. //    printf("default: 0x%04x\n", msg);
  765.     goto defproc;
  766.   }
  767.  
  768. defproc:    
  769.   return DefWindowProc(hwnd, msg, wParam, lParam); 
  770.