freeglut_cursor.c
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:11k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2.  * freeglut_cursor.c
  3.  *
  4.  * The mouse cursor related stuff.
  5.  *
  6.  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
  7.  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
  8.  * Creation date: Thu Dec 16 1999
  9.  *
  10.  * Permission is hereby granted, free of charge, to any person obtaining a
  11.  * copy of this software and associated documentation files (the "Software"),
  12.  * to deal in the Software without restriction, including without limitation
  13.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14.  * and/or sell copies of the Software, and to permit persons to whom the
  15.  * Software is furnished to do so, subject to the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice shall be included
  18.  * in all copies or substantial portions of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  24.  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  */
  27. #include <GL/freeglut.h>
  28. #include "freeglut_internal.h"
  29. #if TARGET_HOST_POSIX_X11
  30.   #include <X11/cursorfont.h>
  31. #endif
  32. /*
  33.  * TODO BEFORE THE STABLE RELEASE:
  34.  *  glutSetCursor()     -- Win32 mappings are incomplete.
  35.  *
  36.  * It would be good to use custom mouse cursor shapes, and introduce
  37.  * an option to display them using glBitmap() and/or texture mapping,
  38.  * apart from the windowing system version.
  39.  */
  40. /* -- PRIVATE FUNCTIONS --------------------------------------------------- */
  41. #if TARGET_HOST_POSIX_X11
  42. /*
  43.  * A factory method for an empty cursor
  44.  */
  45. static Cursor getEmptyCursor( void )
  46. {
  47.     static Cursor cursorNone = None;
  48.     if( cursorNone == None ) {
  49.         char cursorNoneBits[ 32 ];
  50.         XColor dontCare;
  51.         Pixmap cursorNonePixmap;
  52.         memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) );
  53.         memset( &dontCare, 0, sizeof( dontCare ) );
  54.         cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.Display,
  55.                                                    fgDisplay.RootWindow,
  56.                                                    cursorNoneBits, 16, 16 );
  57.         if( cursorNonePixmap != None ) {
  58.             cursorNone = XCreatePixmapCursor( fgDisplay.Display,
  59.                                               cursorNonePixmap, cursorNonePixmap,
  60.                                               &dontCare, &dontCare, 0, 0 );
  61.             XFreePixmap( fgDisplay.Display, cursorNonePixmap );
  62.         }
  63.     }
  64.     return cursorNone;
  65. }
  66. typedef struct tag_cursorCacheEntry cursorCacheEntry;
  67. struct tag_cursorCacheEntry {
  68.     unsigned int cursorShape;    /* an XC_foo value */
  69.     Cursor cachedCursor;         /* None if the corresponding cursor has
  70.                                     not been created yet */
  71. };
  72. /*
  73.  * Note: The arrangement of the table below depends on the fact that
  74.  * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive.
  75.  */ 
  76. static cursorCacheEntry cursorCache[] = {
  77.     { XC_arrow,               None }, /* GLUT_CURSOR_RIGHT_ARROW */
  78.     { XC_top_left_arrow,      None }, /* GLUT_CURSOR_LEFT_ARROW */
  79.     { XC_hand1,               None }, /* GLUT_CURSOR_INFO */
  80.     { XC_pirate,              None }, /* GLUT_CURSOR_DESTROY */
  81.     { XC_question_arrow,      None }, /* GLUT_CURSOR_HELP */
  82.     { XC_exchange,            None }, /* GLUT_CURSOR_CYCLE */
  83.     { XC_spraycan,            None }, /* GLUT_CURSOR_SPRAY */
  84.     { XC_watch,               None }, /* GLUT_CURSOR_WAIT */
  85.     { XC_xterm,               None }, /* GLUT_CURSOR_TEXT */
  86.     { XC_crosshair,           None }, /* GLUT_CURSOR_CROSSHAIR */
  87.     { XC_sb_v_double_arrow,   None }, /* GLUT_CURSOR_UP_DOWN */
  88.     { XC_sb_h_double_arrow,   None }, /* GLUT_CURSOR_LEFT_RIGHT */
  89.     { XC_top_side,            None }, /* GLUT_CURSOR_TOP_SIDE */
  90.     { XC_bottom_side,         None }, /* GLUT_CURSOR_BOTTOM_SIDE */
  91.     { XC_left_side,           None }, /* GLUT_CURSOR_LEFT_SIDE */
  92.     { XC_right_side,          None }, /* GLUT_CURSOR_RIGHT_SIDE */
  93.     { XC_top_left_corner,     None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */
  94.     { XC_top_right_corner,    None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */
  95.     { XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
  96.     { XC_bottom_left_corner,  None }  /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
  97. };
  98. #endif
  99. /* -- INTERNAL FUNCTIONS ---------------------------------------------------- */
  100. /*
  101.  * Set the cursor image to be used for the current window
  102.  */
  103. void fgSetCursor ( SFG_Window *window, int cursorID )
  104. {
  105. #if TARGET_HOST_POSIX_X11
  106.     {
  107.         Cursor cursor;
  108.         /*
  109.          * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows
  110.          * for this, but if there is a system that easily supports a full-
  111.          * window (or full-screen) crosshair, we might consider it.
  112.          */
  113.         int cursorIDToUse =
  114.             ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID;
  115.         if( ( cursorIDToUse >= 0 ) &&
  116.             ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) {
  117.             cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ];
  118.             if( entry->cachedCursor == None ) {
  119.                 entry->cachedCursor =
  120.                     XCreateFontCursor( fgDisplay.Display, entry->cursorShape );
  121.             }
  122.             cursor = entry->cachedCursor;
  123.         } else {
  124.             switch( cursorIDToUse )
  125.             {
  126.             case GLUT_CURSOR_NONE:
  127.                 cursor = getEmptyCursor( );
  128.                 break;
  129.             case GLUT_CURSOR_INHERIT:
  130.                 cursor = None;
  131.                 break;
  132.             default:
  133.                 fgError( "Unknown cursor type: %d", cursorIDToUse );
  134.                 return;
  135.             }
  136.         }
  137.         if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) {
  138.             XUndefineCursor( fgDisplay.Display, window->Window.Handle );
  139.         } else if ( cursor != None ) {
  140.             XDefineCursor( fgDisplay.Display, window->Window.Handle, cursor );
  141.         } else if ( cursorIDToUse != GLUT_CURSOR_NONE ) {
  142.             fgError( "Failed to create cursor" );
  143.         }
  144.     }
  145. #elif TARGET_HOST_MS_WINDOWS
  146.     /*
  147.      * Joe Krahn is re-writing the following code.
  148.      */
  149.     /* Set the cursor AND change it for this window class. */
  150. #if !defined(__MINGW64__) && _MSC_VER <= 1200
  151. #       define MAP_CURSOR(a,b)                                   
  152.         case a:                                                  
  153.             SetCursor( LoadCursor( NULL, b ) );                  
  154.             SetClassLong( window->Window.Handle,                 
  155.                           GCL_HCURSOR,                           
  156.                           ( LONG )LoadCursor( NULL, b ) );       
  157.         break;
  158.     /* Nuke the cursor AND change it for this window class. */
  159. #       define ZAP_CURSOR(a,b)                                   
  160.         case a:                                                  
  161.             SetCursor( NULL );                                   
  162.             SetClassLong( window->Window.Handle,                 
  163.                           GCL_HCURSOR, ( LONG )NULL );           
  164.         break;
  165. #else
  166. #       define MAP_CURSOR(a,b)                                   
  167.         case a:                                                  
  168.             SetCursor( LoadCursor( NULL, b ) );                  
  169.             SetClassLongPtr( window->Window.Handle,              
  170.                           GCLP_HCURSOR,                          
  171.                           ( LONG )( LONG_PTR )LoadCursor( NULL, b ) );       
  172.         break;
  173.     /* Nuke the cursor AND change it for this window class. */
  174. #       define ZAP_CURSOR(a,b)                                   
  175.         case a:                                                  
  176.             SetCursor( NULL );                                   
  177.             SetClassLongPtr( window->Window.Handle,              
  178.                           GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL );          
  179.         break;
  180. #endif
  181.     switch( cursorID )
  182.     {
  183.         MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW,         IDC_ARROW     );
  184.         MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW,          IDC_ARROW     );
  185.         MAP_CURSOR( GLUT_CURSOR_INFO,                IDC_HELP      );
  186.         MAP_CURSOR( GLUT_CURSOR_DESTROY,             IDC_CROSS     );
  187.         MAP_CURSOR( GLUT_CURSOR_HELP,                IDC_HELP      );
  188.         MAP_CURSOR( GLUT_CURSOR_CYCLE,               IDC_SIZEALL   );
  189.         MAP_CURSOR( GLUT_CURSOR_SPRAY,               IDC_CROSS     );
  190.         MAP_CURSOR( GLUT_CURSOR_WAIT,                IDC_WAIT      );
  191.         MAP_CURSOR( GLUT_CURSOR_TEXT,                IDC_IBEAM     );
  192.         MAP_CURSOR( GLUT_CURSOR_CROSSHAIR,           IDC_CROSS     );
  193.         MAP_CURSOR( GLUT_CURSOR_UP_DOWN,             IDC_SIZENS    );
  194.         MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT,          IDC_SIZEWE    );
  195.         MAP_CURSOR( GLUT_CURSOR_TOP_SIDE,            IDC_ARROW     ); /* XXX ToDo */
  196.         MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE,         IDC_ARROW     ); /* XXX ToDo */
  197.         MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE,           IDC_ARROW     ); /* XXX ToDo */
  198.         MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE,          IDC_ARROW     ); /* XXX ToDo */
  199.         MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER,     IDC_SIZENWSE  );
  200.         MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER,    IDC_SIZENESW  );
  201.         MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE  );
  202.         MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER,  IDC_SIZENESW  );
  203.         MAP_CURSOR( GLUT_CURSOR_INHERIT,             IDC_ARROW     ); /* XXX ToDo */
  204.         ZAP_CURSOR( GLUT_CURSOR_NONE,                NULL          );
  205.         MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR,      IDC_CROSS     ); /* XXX ToDo */
  206.     default:
  207.         fgError( "Unknown cursor type: %d", cursorID );
  208.         break;
  209.     }
  210. #endif
  211.     window->State.Cursor = cursorID;
  212. }
  213. /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
  214. /*
  215.  * Set the cursor image to be used for the current window
  216.  */
  217. void FGAPIENTRY glutSetCursor( int cursorID )
  218. {
  219.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetCursor" );
  220.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetCursor" );
  221.     fgSetCursor ( fgStructure.CurrentWindow, cursorID );
  222. }
  223. /*
  224.  * Moves the mouse pointer to given window coordinates
  225.  */
  226. void FGAPIENTRY glutWarpPointer( int x, int y )
  227. {
  228.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWarpPointer" );
  229.     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutWarpPointer" );
  230. #if TARGET_HOST_POSIX_X11
  231.     XWarpPointer(
  232.         fgDisplay.Display,
  233.         None,
  234.         fgStructure.CurrentWindow->Window.Handle,
  235.         0, 0, 0, 0,
  236.         x, y
  237.     );
  238.     /* Make the warp visible immediately. */
  239.     XFlush( fgDisplay.Display );
  240. #elif TARGET_HOST_MS_WINDOWS
  241.     {
  242.         POINT coords;
  243.         coords.x = x;
  244.         coords.y = y;
  245.         /* ClientToScreen() translates {coords} for us. */
  246.         ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
  247.         SetCursorPos( coords.x, coords.y );
  248.     }
  249. #endif
  250. }
  251. /*** END OF FILE ***/