gremlin/libs/glfw/lib/amigaos/amigaos_window.c
2011-01-04 18:11:59 +01:00

831 lines
27 KiB
C

//========================================================================
// GLFW - An OpenGL framework
// File: amigaos_window.c
// Platforms: AmigaOS, MorphOS
// API version: 2.6
// WWW: http://glfw.sourceforge.net
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Camilla Berglund
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
//************************************************************************
//**** GLFW internal functions ****
//************************************************************************
//========================================================================
// _glfwTranslateChar() - Translates an AmigaOS key to Unicode
//========================================================================
static int _glfwTranslateChar( struct IntuiMessage *msg )
{
struct InputEvent event;
unsigned char buffer[ 4 ];
int character;
// Create input event
event.ie_Class = IECLASS_RAWKEY;
event.ie_Code = msg->Code;
event.ie_Qualifier = msg->Qualifier;
event.ie_EventAddress = msg->IAddress;
// Map key event to text string
if( MapRawKey( &event, buffer, 4, NULL ) > 0 )
{
// Valid Unicode character?
character = (int) buffer[ 0 ];
if( (character >= 32 && character <= 126) ||
(character >= 160 && character <= 255) )
{
return character;
}
}
return -1;
}
//========================================================================
// _glfwTranslateKey() - Translates an AmigaOS key to internal coding
//========================================================================
static int _glfwTranslateKey( struct IntuiMessage *msg )
{
int key = msg->Code & 0x7F;
ULONG old_qualifier;
// Special (non printable) keys
switch( key )
{
// Modifier keys
case 0x60: return GLFW_KEY_LSHIFT;
case 0x61: return GLFW_KEY_RSHIFT;
case 0x62: return GLFW_KEY_LCTRL; // ?
case 0x63: return GLFW_KEY_RCTRL; // ?
case 0x64: return GLFW_KEY_LALT;
case 0x65: return GLFW_KEY_RALT;
// Function keys
case 0x50: return GLFW_KEY_F1;
case 0x51: return GLFW_KEY_F2;
case 0x52: return GLFW_KEY_F3;
case 0x53: return GLFW_KEY_F4;
case 0x54: return GLFW_KEY_F5;
case 0x55: return GLFW_KEY_F6;
case 0x56: return GLFW_KEY_F7;
case 0x57: return GLFW_KEY_F8;
case 0x58: return GLFW_KEY_F9;
case 0x59: return GLFW_KEY_F10;
// Other control keys
case 0x45: return GLFW_KEY_ESC;
case 0x42: return GLFW_KEY_TAB;
case 0x44: return GLFW_KEY_ENTER;
case 0x46: return GLFW_KEY_DEL;
case 0x41: return GLFW_KEY_BACKSPACE;
case 0x66: return GLFW_KEY_INSERT; // ?
case 0x4F: return GLFW_KEY_LEFT;
case 0x4E: return GLFW_KEY_RIGHT;
case 0x4C: return GLFW_KEY_UP;
case 0x4D: return GLFW_KEY_DOWN;
// Keypad keys
case 0x0F: return GLFW_KEY_KP_0;
case 0x1D: return GLFW_KEY_KP_1;
case 0x1E: return GLFW_KEY_KP_2;
case 0x1F: return GLFW_KEY_KP_3;
case 0x2D: return GLFW_KEY_KP_4;
case 0x2E: return GLFW_KEY_KP_5;
case 0x2F: return GLFW_KEY_KP_6;
case 0x3D: return GLFW_KEY_KP_7;
case 0x3E: return GLFW_KEY_KP_8;
case 0x3F: return GLFW_KEY_KP_9;
case 0x43: return GLFW_KEY_KP_ENTER;
case 0x5E: return GLFW_KEY_KP_ADD;
case 0x4A: return GLFW_KEY_KP_SUBTRACT;
case 0x5D: return GLFW_KEY_KP_MULTIPLY;
case 0x5C: return GLFW_KEY_KP_DIVIDE;
case 0x3C: return GLFW_KEY_KP_DECIMAL;
default: break;
}
// Printable keys (without modifiers!)
old_qualifier = msg->Qualifier;
msg->Qualifier = 0;
key = _glfwTranslateChar( msg );
msg->Qualifier = old_qualifier;
if( key > 0 )
{
// Make sure it is upper case
key = ToUpper( key );
}
return key;
}
//========================================================================
// _glfwProcessEvents() - Process all pending AmigaOS events
//========================================================================
static int _glfwProcessEvents( void )
{
struct IntuiMessage message, *tmp_message = NULL;
struct MsgPort *msg_port;
int win_closed = GL_FALSE, action;
int x, y;
// Examine pending messages
msg_port = _glfwWin.Window->UserPort;
while( (tmp_message = (struct IntuiMessage *) GetMsg( msg_port )) )
{
// Copy contents of message structure
message = *tmp_message;
// Now reply to the message (we don't need it anymore)
ReplyMsg( (struct Message *) tmp_message );
// Handle different messages
switch( message.Class )
{
// Was the window activated?
case IDCMP_ACTIVEWINDOW:
_glfwWin.Active = GL_TRUE;
break;
// Was the window deactivated?
case IDCMP_INACTIVEWINDOW:
_glfwWin.Active = GL_FALSE;
_glfwInputDeactivation();
break;
// Did we get a keyboard press or release?
case IDCMP_RAWKEY:
action = (message.Code & 0x80) ? GLFW_RELEASE : GLFW_PRESS;
message.Code &= 0x7F;
_glfwInputKey( _glfwTranslateKey( &message ), action );
_glfwInputChar( _glfwTranslateChar( &message ), action );
break;
// Was the mouse moved?
case IDCMP_MOUSEMOVE:
x = message.MouseX;
y = message.MouseY;
if( _glfwWin.PointerHidden )
{
// When pointer is hidden, we get delta moves
x += _glfwInput.MousePosX;
y += _glfwInput.MousePosY;
}
else if( x < 0 || x >= _glfwWin.Width ||
y < 0 || y >= _glfwWin.Height )
{
// Only report mouse moves that are INSIDE client area
break;
}
if( x != _glfwInput.MousePosX || y != _glfwInput.MousePosY )
{
_glfwInput.MousePosX = x;
_glfwInput.MousePosY = y;
if( _glfwWin.MousePosCallback )
{
_glfwWin.MousePosCallback( x, y );
}
}
break;
// Did we get a mouse button event?
case IDCMP_MOUSEBUTTONS:
switch( message.Code )
{
case SELECTUP:
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT,
GLFW_RELEASE );
break;
case SELECTDOWN:
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT,
GLFW_PRESS );
break;
case MENUUP:
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT,
GLFW_RELEASE );
break;
case MENUDOWN:
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT,
GLFW_PRESS );
break;
default:
break;
}
break;
// Was the window size changed?
case IDCMP_NEWSIZE:
_glfwWin.Width = message.IDCMPWindow->GZZWidth;
_glfwWin.Height = message.IDCMPWindow->GZZHeight;
if( _glfwWin.WindowSizeCallback )
{
_glfwWin.WindowSizeCallback( _glfwWin.Width,
_glfwWin.Height );
}
break;
// Was the window contents damaged?
case IDCMP_REFRESHWINDOW:
// Intuition wants us to do this...
BeginRefresh( _glfwWin.Window );
EndRefresh( _glfwWin.Window, TRUE );
// Call user callback function
if( _glfwWin.WindowRefreshCallback )
{
_glfwWin.WindowRefreshCallback();
}
break;
// Was the window closed?
case IDCMP_CLOSEWINDOW:
win_closed = GL_TRUE;
break;
default:
break;
}
}
// Return GL_TRUE if window was closed
return( win_closed );
}
//************************************************************************
//**** Platform implementation functions ****
//************************************************************************
//========================================================================
// _glfwPlatformOpenWindow() - Here is where the window is created, and
// the OpenGL rendering context is created
//========================================================================
int _glfwPlatformOpenWindow( int width, int height, int redbits,
int greenbits, int bluebits, int alphabits, int depthbits,
int stencilbits, int mode, int accumredbits, int accumgreenbits,
int accumbluebits, int accumalphabits, int auxbuffers, int stereo,
int refreshrate )
{
struct TagItem tagList[ 25 ];
int tagNR, accumbits;
// Calculate sum of accumulator bits
accumbits = accumredbits + accumgreenbits + accumbluebits +
accumalphabits;
// Clear window state
_glfwWin.Screen = NULL;
_glfwWin.Window = NULL;
_glfwWin.Context = NULL;
_glfwWin.PointerHidden = 0;
_glfwWin.PointerSprite = NULL;
_glfwWin.InputMP = NULL;
_glfwWin.InputIO = NULL;
// Create input.device message port
if( !(_glfwWin.InputMP = CreatePort( NULL, 0 )) )
{
_glfwPlatformCloseWindow();
return GL_FALSE;
}
// Create input.device I/O request
if( !(_glfwWin.InputIO = (struct IOStdReq *)
CreateExtIO( _glfwWin.InputMP, sizeof(struct IOStdReq) )) )
{
_glfwPlatformCloseWindow();
return GL_FALSE;
}
// Open input.device (for pointer position manipulation)
if( OpenDevice( "input.device", 0,
(struct IORequest *)_glfwWin.InputIO, 0 ) )
{
DeleteExtIO( (struct IORequest *) _glfwWin.InputIO );
_glfwWin.InputIO = NULL;
_glfwPlatformCloseWindow();
return GL_FALSE;
}
// Do we want fullscreen?
if( _glfwWin.Fullscreen )
{
// Open a new Amiga screen
if( !_glfwOpenScreen( &width, &height, &redbits, &greenbits,
&bluebits, refreshrate ) )
{
_glfwWin.Fullscreen = GL_FALSE;
}
}
// Select window properties
tagNR = 0;
tagList[ tagNR ].ti_Tag = WA_Left;
tagList[ tagNR++ ].ti_Data = 0;
tagList[ tagNR ].ti_Tag = WA_Top;
tagList[ tagNR++ ].ti_Data = 0;
tagList[ tagNR ].ti_Tag = WA_IDCMP;
tagList[ tagNR++ ].ti_Data = IDCMP_REFRESHWINDOW |
IDCMP_CLOSEWINDOW |
IDCMP_NEWSIZE |
IDCMP_ACTIVEWINDOW |
IDCMP_INACTIVEWINDOW |
IDCMP_RAWKEY |
IDCMP_MOUSEMOVE |
IDCMP_MOUSEBUTTONS;
tagList[ tagNR ].ti_Tag = WA_ReportMouse;
tagList[ tagNR++ ].ti_Data = TRUE;
tagList[ tagNR ].ti_Tag = WA_RMBTrap;
tagList[ tagNR++ ].ti_Data = TRUE;
tagList[ tagNR ].ti_Tag = WA_NoCareRefresh;
tagList[ tagNR++ ].ti_Data = FALSE;
tagList[ tagNR ].ti_Tag = WA_SimpleRefresh;
tagList[ tagNR++ ].ti_Data = TRUE;
tagList[ tagNR ].ti_Tag = WA_Activate;
tagList[ tagNR++ ].ti_Data = TRUE;
tagList[ tagNR ].ti_Tag = WA_CloseGadget;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE;
tagList[ tagNR ].ti_Tag = WA_SizeGadget;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : ( _glfwWinHints.WindowNoResize ? FALSE : TRUE );
tagList[ tagNR ].ti_Tag = WA_DepthGadget;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE;
tagList[ tagNR ].ti_Tag = WA_DragBar;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? FALSE : TRUE;
tagList[ tagNR ].ti_Tag = WA_Borderless;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? TRUE : FALSE;
tagList[ tagNR ].ti_Tag = WA_Backdrop;
tagList[ tagNR++ ].ti_Data = _glfwWin.Fullscreen ? TRUE : FALSE;
if( _glfwWin.Fullscreen )
{
tagList[ tagNR ].ti_Tag = WA_CustomScreen;
tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Screen;
tagList[ tagNR ].ti_Tag = WA_Width;
tagList[ tagNR++ ].ti_Data = width;
tagList[ tagNR ].ti_Tag = WA_Height;
tagList[ tagNR++ ].ti_Data = height;
}
else
{
tagList[ tagNR ].ti_Tag = WA_GimmeZeroZero;
tagList[ tagNR++ ].ti_Data = TRUE;
tagList[ tagNR ].ti_Tag = WA_InnerWidth;
tagList[ tagNR++ ].ti_Data = width;
tagList[ tagNR ].ti_Tag = WA_InnerHeight;
tagList[ tagNR++ ].ti_Data = height;
tagList[ tagNR ].ti_Tag = WA_MinWidth;
tagList[ tagNR++ ].ti_Data = 20;
tagList[ tagNR ].ti_Tag = WA_MinHeight;
tagList[ tagNR++ ].ti_Data = 20;
tagList[ tagNR ].ti_Tag = WA_MaxWidth;
tagList[ tagNR++ ].ti_Data = 9999;
tagList[ tagNR ].ti_Tag = WA_MaxHeight;
tagList[ tagNR++ ].ti_Data = 9999;
tagList[ tagNR ].ti_Tag = WA_Title;
tagList[ tagNR++ ].ti_Data = (ULONG) "GLFW Window";
tagList[ tagNR ].ti_Tag = WA_ScreenTitle;
tagList[ tagNR++ ].ti_Data = (ULONG) "GLFW Application";
}
tagList[ tagNR ].ti_Tag = TAG_DONE;
// Open window
_glfwWin.Window = OpenWindowTagList( NULL, tagList );
if( !_glfwWin.Window )
{
_glfwPlatformCloseWindow();
return GL_FALSE;
}
// Fullscreen/windowed post fixups
if( _glfwWin.Fullscreen )
{
// Don't show screen title
ShowTitle( _glfwWin.Screen, FALSE );
// Remember window size
_glfwWin.Width = _glfwWin.Window->Width;
_glfwWin.Height = _glfwWin.Window->Height;
}
else
{
// If we are not in fullscreen mode, get screen handle from window
_glfwWin.Screen = _glfwWin.Window->WScreen;
// Get ModeID for the current video mode
_glfwWin.ModeID = GetVPModeID( &_glfwWin.Screen->ViewPort );
// Remember window size
_glfwWin.Width = _glfwWin.Window->GZZWidth;
_glfwWin.Height = _glfwWin.Window->GZZHeight;
}
// Put window on top
WindowToFront( _glfwWin.Window );
// Create OpenGL context
#ifdef _GLFW_STORMMESA
tagNR = 0;
tagList[ tagNR ].ti_Tag = AMA_Window;
tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Window;
tagList[ tagNR ].ti_Tag = AMA_RastPort;
tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Window->RPort;
tagList[ tagNR ].ti_Tag = AMA_Screen;
tagList[ tagNR++ ].ti_Data = (ULONG) _glfwWin.Screen;
tagList[ tagNR ].ti_Tag = AMA_Left;
tagList[ tagNR++ ].ti_Data = 0;
tagList[ tagNR ].ti_Tag = AMA_Bottom;
tagList[ tagNR++ ].ti_Data = 0;
tagList[ tagNR ].ti_Tag = AMA_Width;
tagList[ tagNR++ ].ti_Data = _glfwWin.Width;
tagList[ tagNR ].ti_Tag = AMA_Height;
tagList[ tagNR++ ].ti_Data = _glfwWin.Height;
tagList[ tagNR ].ti_Tag = AMA_DoubleBuf;
tagList[ tagNR++ ].ti_Data = GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_RGBMode;
tagList[ tagNR++ ].ti_Data = GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_AlphaFlag;
tagList[ tagNR++ ].ti_Data = alphabits ? GL_TRUE : GL_FALSE;
tagList[ tagNR ].ti_Tag = AMA_NoDepth;
tagList[ tagNR++ ].ti_Data = depthbits ? GL_FALSE : GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_NoStencil;
tagList[ tagNR++ ].ti_Data = stencilbits ? GL_FALSE : GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_NoAccum;
tagList[ tagNR++ ].ti_Data = accumbits ? GL_FALSE : GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_DirectRender;
tagList[ tagNR++ ].ti_Data = GL_TRUE;
tagList[ tagNR ].ti_Tag = AMA_DrawMode;
tagList[ tagNR++ ].ti_Data = AMESA_AGA_C2P;
tagList[ tagNR ].ti_Tag = TAG_DONE;
_glfwWin.Context = AmigaMesaCreateContext( tagList );
#endif
if( !_glfwWin.Context )
{
_glfwPlatformCloseWindow();
return GL_FALSE;
}
// Make current
#ifdef _GLFW_STORMMESA
AmigaMesaMakeCurrent( _glfwWin.Context, _glfwWin.Context->buffer );
#endif
return GL_TRUE;
}
//========================================================================
// _glfwPlatformCloseWindow() - Properly kill the window/video display
//========================================================================
void _glfwPlatformCloseWindow( void )
{
// Restore mouse pointer (if hidden)
_glfwPlatformShowMouseCursor();
// Destroy OpenGL context
if( _glfwWin.Context )
{
#ifdef _GLFW_STORMMESA
AmigaMesaDestroyContext( _glfwWin.Context );
#endif
_glfwWin.Context = NULL;
}
// Close window
if( _glfwWin.Window )
{
CloseWindow( _glfwWin.Window );
_glfwWin.Window = NULL;
}
// Close screen
if( _glfwWin.Fullscreen && _glfwWin.Screen )
{
CloseScreen( _glfwWin.Screen );
}
_glfwWin.Screen = NULL;
// Close input device I/O request
if( _glfwWin.InputIO )
{
CloseDevice( (struct IORequest *) _glfwWin.InputIO );
DeleteExtIO( (struct IORequest *) _glfwWin.InputIO );
_glfwWin.InputIO = NULL;
}
// Close input device message port
if( _glfwWin.InputMP )
{
DeletePort( _glfwWin.InputMP );
_glfwWin.InputMP = NULL;
}
}
//========================================================================
// _glfwPlatformSetWindowTitle() - Set the window title.
//========================================================================
void _glfwPlatformSetWindowTitle( const char *title )
{
if( !_glfwWin.Fullscreen )
{
SetWindowTitles( _glfwWin.Window, (char*) title, (char*) title );
}
}
//========================================================================
// _glfwPlatformSetWindowSize() - Set the window size.
//========================================================================
void _glfwPlatformSetWindowSize( int width, int height )
{
if( !_glfwWin.Fullscreen )
{
SizeWindow( _glfwWin.Window, width-_glfwWin.Width,
height-_glfwWin.Height );
}
}
//========================================================================
// _glfwPlatformSetWindowPos() - Set the window position.
//========================================================================
void _glfwPlatformSetWindowPos( int x, int y )
{
if( !_glfwWin.Fullscreen )
{
ChangeWindowBox( _glfwWin.Window, x, y, _glfwWin.Window->Width,
_glfwWin.Window->Height );
}
}
//========================================================================
// _glfwPlatformIconfyWindow() - Window iconification
//========================================================================
void _glfwPlatformIconifyWindow( void )
{
if( _glfwWin.Fullscreen )
{
ScreenToBack( _glfwWin.Screen );
WBenchToFront();
_glfwWin.Iconified = GL_TRUE;
}
}
//========================================================================
// _glfwPlatformRestoreWindow() - Window un-iconification
//========================================================================
void _glfwPlatformRestoreWindow( void )
{
if( _glfwWin.Fullscreen )
{
ScreenToFront( _glfwWin.Screen );
}
WindowToFront( _glfwWin.Window );
ActivateWindow( _glfwWin.Window );
_glfwWin.Iconified = GL_FALSE;
}
//========================================================================
// _glfwPlatformSwapBuffers() - Swap buffers (double-buffering) and poll
// any new events.
//========================================================================
void _glfwPlatformSwapBuffers( void )
{
#ifdef _GLFW_STORMMESA
AmigaMesaSwapBuffers( _glfwWin.Context );
#endif
}
//========================================================================
// _glfwPlatformSwapInterval() - Set double buffering swap interval
//========================================================================
void _glfwPlatformSwapInterval( int interval )
{
// Not supported
}
//========================================================================
// _glfwPlatformRefreshWindowParams()
//========================================================================
void _glfwPlatformRefreshWindowParams( void )
{
int refresh;
GLint x;
GLboolean b;
// This function is not proerly implemented yet. We use OpenGL for
// getting framebuffer format information - we should use some
// alternate interface (such as glX under the X Window System), but
// StormMesa does not seem to provide this.
// Fill out information
_glfwWin.Accelerated = GL_TRUE;
glGetIntegerv( GL_RED_BITS, &x );
_glfwWin.RedBits = x;
glGetIntegerv( GL_GREEN_BITS, &x );
_glfwWin.GreenBits = x;
glGetIntegerv( GL_BLUE_BITS, &x );
_glfwWin.BlueBits = x;
glGetIntegerv( GL_ALPHA_BITS, &x );
_glfwWin.AlphaBits = x;
glGetIntegerv( GL_DEPTH_BITS, &x );
_glfwWin.DepthBits = x;
glGetIntegerv( GL_STENCIL_BITS, &x );
_glfwWin.StencilBits = x;
glGetIntegerv( GL_ACCUM_RED_BITS, &x );
_glfwWin.AccumRedBits = x;
glGetIntegerv( GL_ACCUM_GREEN_BITS, &x );
_glfwWin.AccumGreenBits = x;
glGetIntegerv( GL_ACCUM_BLUE_BITS, &x );
_glfwWin.AccumBlueBits = x;
glGetIntegerv( GL_ACCUM_ALPHA_BITS, &x );
_glfwWin.AccumAlphaBits = x;
glGetIntegerv( GL_AUX_BUFFERS, &x );
_glfwWin.AuxBuffers = x;
glGetBooleanv( GL_AUX_BUFFERS, &b );
_glfwWin.Stereo = b ? GL_TRUE : GL_FALSE;
// Get ModeID information (refresh rate)
_glfwGetModeIDInfo( _glfwWin.ModeID, NULL, NULL, NULL, NULL, NULL,
&refresh );
_glfwWin.RefreshRate = refresh;
}
//========================================================================
// _glfwPlatformPollEvents() - Poll for new window and input events
//========================================================================
void _glfwPlatformPollEvents( void )
{
int winclosed;
// Process all pending window events
winclosed = GL_FALSE;
if( _glfwProcessEvents() )
{
winclosed = GL_TRUE;
}
// Was there a window close request?
if( winclosed && _glfwWin.WindowCloseCallback )
{
// Check if the program wants us to close the window
winclosed = _glfwWin.WindowCloseCallback();
}
if( winclosed )
{
glfwCloseWindow();
}
}
//========================================================================
// _glfwPlatformWaitEvents() - Wait for new window and input events
//========================================================================
void _glfwPlatformWaitEvents( void )
{
// Wait for new events
Wait( 1L << _glfwWin.Window->UserPort->mp_SigBit );
// Poll new events
_glfwPlatformPollEvents();
}
//========================================================================
// _glfwPlatformHideMouseCursor() - Hide mouse cursor (lock it)
//========================================================================
void _glfwPlatformHideMouseCursor( void )
{
// We only allow this under fullscreen right now, since we can't rely
// on the pointer position in windowed mode! Perhaps it's possible to
// "steal" the mouse with input.device or something...?
if( !_glfwWin.PointerHidden && _glfwWin.Fullscreen )
{
// Allocate chip memory for the blank mouse pointer
_glfwWin.PointerSprite = AllocVec( 128, MEMF_CHIP | MEMF_CLEAR );
if( _glfwWin.PointerSprite )
{
// Switch to blank/transparent pointer
SetPointer( _glfwWin.Window, (UWORD *) _glfwWin.PointerSprite,
1, 1, 0, 0 );
_glfwWin.PointerHidden = 1;
// Switch to mouse delta movement
Forbid();
_glfwWin.Window->IDCMPFlags |= IDCMP_DELTAMOVE;
Permit();
}
}
}
//========================================================================
// _glfwPlatformShowMouseCursor() - Show mouse cursor (unlock it)
//========================================================================
void _glfwPlatformShowMouseCursor( void )
{
if( _glfwWin.PointerHidden )
{
// Switch to absolute mouse movement
Forbid();
_glfwWin.Window->IDCMPFlags &= (0xFFFFFFFF^IDCMP_DELTAMOVE);
Permit();
// Change back to normal pointer
ClearPointer( _glfwWin.Window );
if( _glfwWin.PointerSprite )
{
FreeVec( _glfwWin.PointerSprite );
_glfwWin.PointerSprite = NULL;
}
_glfwWin.PointerHidden = 0;
}
}
//========================================================================
// _glfwPlatformSetMouseCursorPos() - Set physical mouse cursor position
//========================================================================
void _glfwPlatformSetMouseCursorPos( int x, int y )
{
struct IEPointerPixel ppxl;
struct InputEvent event;
// Adjust coordinates to window client area upper left corner
x += _glfwWin.Window->LeftEdge;
y += _glfwWin.Window->TopEdge;
/* Set up IEPointerPixel fields */
ppxl.iepp_Screen = _glfwWin.Screen;
ppxl.iepp_Position.X = x;
ppxl.iepp_Position.Y = y;
/* Set up InputEvent fields */
event.ie_EventAddress = (APTR)&ppxl; /* IEPointerPixel */
event.ie_NextEvent = NULL;
event.ie_Class = IECLASS_NEWPOINTERPOS; /* new mouse pos */
event.ie_SubClass = IESUBCLASS_PIXEL; /* on pixel */
event.ie_Code = IECODE_NOBUTTON;
event.ie_Qualifier = 0; /* absolute pos */
/* Set up I/O request */
_glfwWin.InputIO->io_Data = (APTR)&event;
_glfwWin.InputIO->io_Length = sizeof(struct InputEvent);
_glfwWin.InputIO->io_Command = IND_WRITEEVENT;
/* Perform I/O (move mouse cursor) */
DoIO( (struct IORequest *)_glfwWin.InputIO );
}