1 /*
2  * fg_cursor_mswin.c
3  *
4  * The Windows-specific mouse cursor related stuff.
5  *
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
7  * Written by John F. Fay, <fayjf@sourceforge.net>
8  * Creation date: Thu Jan 19, 2012
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 
28 #include <GL/freeglut.h>
29 #include "../fg_internal.h"
30 
31 
32 
fgPlatformSetCursor(SFG_Window * window,int cursorID)33 void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
34 {
35     /*
36      * Joe Krahn is re-writing the following code.
37      */
38     /* Set the cursor AND change it for this window class. */
39 #if !defined(__MINGW64__) && _MSC_VER <= 1200
40 #       define MAP_CURSOR(a,b)                                   \
41         case a:                                                  \
42             SetCursor( LoadCursor( NULL, b ) );                  \
43             SetClassLong( window->Window.Handle,                 \
44                           GCL_HCURSOR,                           \
45                           ( LONG )LoadCursor( NULL, b ) );       \
46         break;
47     /* Nuke the cursor AND change it for this window class. */
48 #       define ZAP_CURSOR(a,b)                                   \
49         case a:                                                  \
50             SetCursor( NULL );                                   \
51             SetClassLong( window->Window.Handle,                 \
52                           GCL_HCURSOR, ( LONG )NULL );           \
53         break;
54 #else
55 #       define MAP_CURSOR(a,b)                                   \
56         case a:                                                  \
57             SetCursor( LoadCursor( NULL, b ) );                  \
58             SetClassLongPtr( window->Window.Handle,              \
59                           GCLP_HCURSOR,                          \
60                           ( LONG )( LONG_PTR )LoadCursor( NULL, b ) );       \
61         break;
62     /* Nuke the cursor AND change it for this window class. */
63 #       define ZAP_CURSOR(a,b)                                   \
64         case a:                                                  \
65             SetCursor( NULL );                                   \
66             SetClassLongPtr( window->Window.Handle,              \
67                           GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL );          \
68         break;
69 #endif
70 
71     switch( cursorID )
72     {
73         MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW,         IDC_ARROW     );
74         MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW,          IDC_ARROW     ); /* XXX ToDo */
75         MAP_CURSOR( GLUT_CURSOR_INFO,                IDC_HELP      );
76         MAP_CURSOR( GLUT_CURSOR_DESTROY,             IDC_CROSS     );
77         MAP_CURSOR( GLUT_CURSOR_HELP,                IDC_HELP      );
78         MAP_CURSOR( GLUT_CURSOR_CYCLE,               IDC_SIZEALL   );
79         MAP_CURSOR( GLUT_CURSOR_SPRAY,               IDC_CROSS     );
80         MAP_CURSOR( GLUT_CURSOR_WAIT,                IDC_WAIT      );
81         MAP_CURSOR( GLUT_CURSOR_TEXT,                IDC_IBEAM     );
82         MAP_CURSOR( GLUT_CURSOR_CROSSHAIR,           IDC_CROSS     );
83         MAP_CURSOR( GLUT_CURSOR_UP_DOWN,             IDC_SIZENS    );
84         MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT,          IDC_SIZEWE    );
85         MAP_CURSOR( GLUT_CURSOR_TOP_SIDE,            IDC_UPARROW   );
86         MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE,         IDC_ARROW     ); /* XXX ToDo */
87         MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE,           IDC_ARROW     ); /* XXX ToDo */
88         MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE,          IDC_ARROW     ); /* XXX ToDo */
89         MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER,     IDC_SIZENWSE  );
90         MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER,    IDC_SIZENESW  );
91         MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE  );
92         MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER,  IDC_SIZENESW  );
93         ZAP_CURSOR( GLUT_CURSOR_NONE,                NULL          );
94         MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR,      IDC_CROSS     ); /* XXX ToDo */
95     case GLUT_CURSOR_INHERIT:
96         {
97             SFG_Window *temp_window = window;
98             while (temp_window->Parent)
99             {
100                 temp_window = temp_window->Parent;
101                 if (temp_window->State.Cursor != GLUT_CURSOR_INHERIT)
102                 {
103                     fgPlatformSetCursor(window,temp_window->State.Cursor);
104                     return;
105                 }
106             }
107             /* No parent, or no parent with cursor type set. Fall back to default */
108             fgPlatformSetCursor(window,GLUT_CURSOR_LEFT_ARROW);
109         }
110         break;
111 
112     default:
113         fgError( "Unknown cursor type: %d", cursorID );
114         break;
115     }
116 }
117 
118 
fgPlatformWarpPointer(int x,int y)119 void fgPlatformWarpPointer ( int x, int y )
120 {
121     POINT coords;
122     coords.x = x;
123     coords.y = y;
124 
125     /* ClientToScreen() translates {coords} for us. */
126     ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
127     SetCursorPos( coords.x, coords.y );
128 }
129 
130 
fghPlatformGetCursorPos(const SFG_Window * window,GLboolean client,SFG_XYUse * mouse_pos)131 void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos)
132 {
133     /* Get current pointer location in screen coordinates (if client is false or window is NULL), else
134      * Get current pointer location relative to top-left of client area of window (if client is true and window is not NULL)
135      */
136     POINT pos;
137     GetCursorPos(&pos);
138 
139     /* convert to client coords if wanted */
140     if (client && window && window->Window.Handle)
141         ScreenToClient(window->Window.Handle,&pos);
142 
143     mouse_pos->X = pos.x;
144     mouse_pos->Y = pos.y;
145     mouse_pos->Use = GL_TRUE;
146 }
147