File: cpw_window.c/***************************************************************************/
/* */
/* cpw_window.c */
/* */
/* Window management and adapter event interface. */
/* */
/* Copyright 2001-2002 by */
/* Jim Mathies, */
/* */
/* This file is part of the Cpw project, and may only be used, */
/* modified, and distributed under the terms of the Cpw project */
/* license. By continuing to use, modify, or distribute this file */
/* you indicate that you have read the license and understand and */
/* accept it fully. */
/* */
/* File Platform: cross */
/* */
/***************************************************************************/
#include "cpw_window.h"
#include "cpw_windowlist.h"
#include "cpw_event.h"
#include "cpw_main.h"
#include "cpw_error.h"
#include CPW_LOCALHOST_H
/*************************************************************************/
/* */
/* init and exit. */
/* */
/*************************************************************************/
/* init */
bool cpw_window_init( pCpw cpw )
{
if ( cpw_windowlist_init( cpw ) == 0 ) { return false; }
return true;
}
/* send a close message to all open windows */
void cpw_window_close( pCpw cpw )
{
cpw_window_closeall( cpw );
}
/* exit */
void cpw_window_exit( pCpw cpw )
{
cpw_window_destroyall( cpw );
cpw_windowlist_exit( cpw );
}
/*************************************************************************/
/* */
/* internal window management. */
/* */
/*************************************************************************/
/* create a new window. returns 0 on failure */
uint_32 cpw_window_create( pCpw cpw, char* title, uint_32 x, uint_32 y,
uint_32 width, uint_32 height )
{
CpwWindowStruct * window;
window = (CpwWindowStruct *) cpwmalloc( sizeof( CpwWindowStruct ) );
if ( !window ) {
cpw_error_set( cpw, cpw_error_outofmemory );
return 0;
}
memset( window, 0, sizeof( CpwWindowStruct ) );
/* init basic window properties */
window->x = x;
window->y = y;
window->width = width;
window->height = height;
window->cursor = CursorArrow;
window->fullscreen = false;
window->bx = window->x;
window->by = window->y;
window->bwidth = window->width;
window->bheight = window->height;
window->id = cpw_windowlist_insert( cpw, window );
/* localhost calls set the error info on failure */
window->plhwc = cpw_localhost_createwindow( cpw, window->id, title,
x, y, width, height,
cpw->win_properties, cpw->win_expectmenu );
if ( window->plhwc == 0 )
return 0;
/* init opengl for this window */
if ( cpw_localhost_setpixelformat( cpw, window->plhwc ) == false )
return 0;
if ( cpw_localhost_createglcontext( cpw, window->plhwc ) == false )
return 0;
/* set to window to foreground */
cpw_localhost_setforeground( window );
cpw->win_foregroundid = window->id;
/* make this windows rendering context current */
cpw->win_currentid = 0;
cpw_window_makecurrent( cpw, window->id );
/* save the window's title */
setString( &window->title, title );
/* inject first three events a window receives into the stack */
cpw_event_insert( cpw, window->id, CPW_CREATE_EVENT, 0, 0, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_POSITION_EVENT, x, y, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_RESHAPE_EVENT, width, height, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
/* return the id */
return window->id;
}
uint_32 cpw_window_createfullscreen( pCpw cpw )
{
CpwWindowStruct * window;
window = (CpwWindowStruct *) cpwmalloc( sizeof( CpwWindowStruct ) );
if ( !window ) {
cpw_error_set( cpw, cpw_error_outofmemory );
return 0;
}
memset( window, 0, sizeof( CpwWindowStruct ) );
/* init fullscreen window properties */
window->x = 0;
window->y = 0;
window->width = cpw->cpw_screenwidth;
window->height = cpw->cpw_screenheight;
window->cursor = CursorNone;
window->fullscreen = true;
window->bx = window->x;
window->by = window->y;
window->bwidth = window->width;
window->bheight = window->height;
window->id = cpw_windowlist_insert( cpw, window );
/* localhost calls set the error info on failure */
window->plhwc = cpw_localhost_createfullscreenwindow( cpw, window->id, "fullscreen" );
if ( window->plhwc == 0 )
return 0;
if ( cpw_localhost_setpixelformat( cpw, window->plhwc ) == false )
return 0;
if ( cpw_localhost_createglcontext( cpw, window->plhwc ) == false )
return 0;
/* set to foreground */
cpw_localhost_setforeground( window );
cpw->win_foregroundid = window->id;
cpw->win_currentid = 0;
cpw_window_makecurrent( cpw, window->id );
setString( &window->title, "fullscreen" );
cpw_event_insert( cpw, window->id, CPW_CREATE_EVENT, 0, 0, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_RESHAPE_EVENT, cpw->cpw_screenwidth, cpw->cpw_screenheight, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
/* return the id */
return window->id;
}
/* destroy a window and it's resources */
bool cpw_window_destroy( pCpw cpw, pCpwWin window )
{
freeStr( &window->title );
cpw_localhost_destroyglcontext( cpw, window->plhwc );
cpw_localhost_destroywindow( cpw, window );
cpwfree( window );
return true;
}
/* send close message to all open windows */
bool cpw_window_closeall( pCpw cpw )
{
pCpwWin window;
window = cpw_windowlist_iteratestart( cpw );
if ( window == 0 ) return true;
while ( window != 0 ) {
cpw_event_insert( cpw, window->id, CPW_DESTROY_EVENT, 0, 0, 0, 0, 0 );
window = cpw_windowlist_iteratenext( cpw );
}
return true;
}
/* destroy all open windows and their resources */
bool cpw_window_destroyall( pCpw cpw )
{
pCpwWin window;
window = cpw_windowlist_iteratestart( cpw );
if ( window == 0 ) return true;
while ( window != 0 ) {
cpw_window_destroy( cpw, window );
window = cpw_windowlist_iteratenext( cpw );
}
/* windowlist is deleted in windowlist_exit */
return true;
}
/* make a window's context current for rendering */
bool cpw_window_makecurrent( pCpw cpw, uint_32 id )
{
pCpwWin window;
#ifdef CPW_COMPILEOPT_CURRENTCONTEXTCACHING
if ( cpw->win_currentid == id ) return true;
#endif
window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) return false;
cpw->win_currentid = id;
cpw_localhost_makecurrent( cpw, window->plhwc );
return true;
}
/*************************************************************************/
/* */
/* window api */
/* */
/*************************************************************************/
/* creation */
uint_32
cpwCreateWindow( pCpw cpw, char * title )
{
uint_32 id = cpw_window_create( cpw, title, cpw->win_initx, cpw->win_inity, cpw->win_initwidth, cpw->win_initheight );
return id;
}
/* creation */
uint_32
cpwCreateWindowEx( pCpw cpw, char * title, uint_32 x, uint_32 y, uint_32 width, uint_32 height )
{
uint_32 id = cpw_window_create( cpw, title, x, y, width, height );
return id;
}
/* create a brand spankin new fullscreen window */
uint_32 cpwCreateFullscreenWindow( pCpw cpw )
{
if ( !cpw_window_createfullscreen( cpw ) )
return false;
return true;
}
/* close and destroy */
bool
cpwDestroyWindow( pCpw cpw, uint_32 id )
{
bool res;
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
cpw_windowlist_remove( cpw, id );
res = cpw_window_destroy( cpw, window );
#ifdef CPW_COMPILEOPT_SHUTDOWNONFIRSTWINDOW
/* shutdown the application on first window close */
if ( id == 1 ) cpwBreakMainLoop( cpw );
#endif
return res;
}
/* set the title */
bool
cpwSetWindowTitle( pCpw cpw, char * title, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
setString( &window->title, title );
return cpw_localhost_setwindowtitle( window );
}
/* position on the desktop */
bool
cpwPositionWindow( pCpw cpw, uint_32 x, uint_32 y, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
window->x = x;
window->y = y;
cpw_event_insert( cpw, window->id, CPW_POSITION_EVENT, window->x, window->y, 0, 0, 0 );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return cpw_localhost_positionwindow( window );
}
/* resize the window frame */
bool
cpwReshapeWindow( pCpw cpw, uint_32 width, uint_32 height, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
window->width = width;
window->height = height;
cpw_event_insert( cpw, id, CPW_RESHAPE_EVENT, width, height, 0, 0, 0 );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return cpw_localhost_reshapewindow( window );
}
/* convert to a fullscreen window to a normal window */
bool cpwStandardWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
if ( window->fullscreen == false ) return true;
if ( !cpw_localhost_standardizewindow( cpw, window ) )
return false;
/* restore old dimensions */
window->x = window->bx;
window->y = window->by;
window->width = window->bwidth;
window->height = window->bheight;
window->fullscreen = false;
/* set to window to foreground */
cpwSetForegroundWindow( cpw, id );
cpw_localhost_positionwindow( window );
cpw_localhost_reshapewindow( window );
/* inject resize and position events */
cpw_event_insert( cpw, window->id, CPW_RESHAPE_EVENT, window->width, window->height, 0, 0, 0 );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return true;
}
/* convert to an existing window to a fullscreen window */
bool cpwFullscreenWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) return false;
if ( window->fullscreen == true ) return true;
/* save the old dimensions */
window->bx = window->x;
window->by = window->y;
window->bwidth = window->width;
window->bheight = window->height;
if ( !cpw_localhost_fullscreenwindow( cpw, window ) )
return false;
window->fullscreen = true;
/* set to window to foreground */
cpwSetForegroundWindow( cpw, id );
/* get the new dimensions */
cpw_localhost_windowinfo( window );
/* inject resize events */
cpw_event_insert( cpw, id, CPW_RESHAPE_EVENT, cpw->cpw_screenwidth, cpw->cpw_screenheight, 0, 0, 0 );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return true;
}
/* maximize a window */
bool cpwMaximizeWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
/* save the old dimensions */
window->bx = window->x;
window->by = window->y;
window->bwidth = window->width;
window->bheight = window->height;
if ( !cpw_localhost_maximizewindow( window ) ) {
return false;
}
/* get the new dimensions */
cpw_localhost_windowinfo( window );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return true;
}
/* iconify the window to the task bar */
bool
cpwIconifyWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
/* save the old dimensions */
window->bx = window->x;
window->by = window->y;
window->bwidth = window->width;
window->bheight = window->height;
return cpw_localhost_inconifywindow( window );
}
/* restore an iconic or maximized window */
bool
cpwRestoreWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
cpw_localhost_restorewindow( window );
/* restore old dimensions */
window->x = window->bx;
window->y = window->by;
window->width = window->bwidth;
window->height = window->bheight;
//cpw_localhost_positionwindow( window );
//cpw_localhost_reshapewindow( window );
cpw_event_insert( cpw, window->id, CPW_POSITION_EVENT, window->x, window->y, 0, 0, 0 );
cpw_event_insert( cpw, window->id, CPW_RESHAPE_EVENT, window->width, window->height, 0, 0, 0 );
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return true;
}
/* get the foreground window id */
uint_32
cpwGetWindow( pCpw cpw )
{
pCpwWin window = cpw_windowlist_lookup( cpw, cpw->win_foregroundid );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return 0;
}
return window->id;
}
/* set the window's rendering context current */
bool
cpwSetWindow( pCpw cpw, uint_32 id )
{
return cpw_window_makecurrent( cpw, id );
}
/* move the window to the foreground */
bool
cpwSetForegroundWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
if ( cpw_localhost_setforeground( window ) ) {
cpw->win_foregroundid = window->id;
return true;
}
cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
return false;
}
/* pop the window below this one up to the foreground */
bool
cpwPopWindow( pCpw cpw )
{
pCpwWin window = cpw_windowlist_lookup( cpw, cpw->win_foregroundid );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return cpw_localhost_popwindow( window );
}
/* push the window below by one in the z-order */
bool
cpwPushWindow( pCpw cpw )
{
pCpwWin window = cpw_windowlist_lookup( cpw, cpw->win_foregroundid );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return cpw_localhost_pushwindow( window );
}
/* hide a window completely from view */
bool
cpwHideWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return cpw_localhost_hidewindow( window );
}
/* restore a hidden window */
bool
cpwShowWindow( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return cpw_localhost_showwindow( window );
}
/* post a paint message to all windows */
bool
cpwPostRedisplay( pCpw cpw )
{
pCpwWin window;
window = cpw_windowlist_iteratestart( cpw );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
while ( window != 0 ) {
cpw_event_insert( cpw, window->id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
window = cpw_windowlist_iteratenext( cpw );
}
return true;
}
/* post a paint message to a particular window */
bool
cpwPostWindowRedisplay( pCpw cpw, uint_32 id )
{
/* Depending on whether or not you care about accurate event order.
Sending the display event directly increases performance slightly
but the event will not be in it's 'proper order' with respect to
other events. Be careful with this mode, sometimes you will get a draw
event before the initial reshape event. */
/* 'correct ordering' */
return cpw_event_insert( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0, 0 );
/* 'direct mode' */
/* return cpw_event_insertnext( cpw, id, CPW_DISPLAY_EVENT, 0, 0, 0, 0 ); */
}
/* swap all double buffered windows */
bool
cpwSwapBuffers( pCpw cpw )
{
pCpwWin window;
bool res = true;
window = cpw_windowlist_iteratestart( cpw );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
while ( window != 0 ) {
res = res & cpw_localhost_swapbuffers( window->plhwc );
window = cpw_windowlist_iteratenext( cpw );
}
return res;
}
/* swap a particular double buffered window */
bool
cpwSwapWindowBuffers( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return cpw_localhost_swapbuffers( window->plhwc );
}
/* set a store the cursor to be used when the mouse is over the window */
bool
cpwSetCursor( pCpw cpw, CpwCursor cursor, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
if ( cpw->win_foregroundid != (uint_32)id ) return false;
if ( window->cursorpresent == false ) return false;
window->cursor = cursor;
cpw_localhost_setcursor( cpw, window );
return false;
}
/* center the cursor in the center of the windows client area. */
/* the window must be the foreground window */
bool
cpwCenterCursor( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
if ( cpw->win_foregroundid != (uint_32)id ) return false;
if ( window->cursorpresent == false ) return false;
cpw_localhost_windowinfo( window );
return cpw_localhost_centercursor( window );
}
/* position the cursor in the windows client area. */
/* the window must be the foreground window */
bool
cpwPositionCursor( pCpw cpw, uint_32 x, uint_32 y, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
if ( cpw->win_foregroundid != (uint_32)id ) return false;
if ( window->cursorpresent == false ) return false;
cpw_localhost_windowinfo( window );
return cpw_localhost_positioncursor( window, x, y );
}
/* generate a CpwWindowList containing information about all windows */
bool cpwListWindows( pCpw cpw, CpwWindowList * list )
{
pCpwWin window;
uint_32 count = 0;
if ( list == 0 ) {
cpw_error_set( cpw, cpw_error_invalidparameter );
return false;
}
memset( list, 0, sizeof( CpwWindowList ) );
window = cpw_windowlist_iteratestart( cpw );
if ( window == 0 ) {
list->size = 0;
return true;
}
while ( window != 0 ) {
cpw_localhost_windowinfo( window );
list->list[count].id = (uint_16)window->id;
list->list[count].x = (uint_16)window->x;
list->list[count].y = (uint_16)window->y;
list->list[count].width = (uint_16)window->width;
list->list[count].height = (uint_16)window->height;
list->list[count].fullscreen = window->fullscreen;
if ( window->id == cpw->win_foregroundid )
list->list[count].foreground = true;
else
list->list[count].foreground = false;
window = cpw_windowlist_iteratenext( cpw );
count++;
if ( count == CPW_MAX_WINLIST ) break;
}
list->size = count;
return true;
}
/* generate a CpwWindowInfo containing information about a particular window */
bool cpwGetWindowInfo( pCpw cpw, CpwWindowInfo * info, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) return false;
if ( info == 0 ) {
cpw_error_set( cpw, cpw_error_invalidparameter );
return false;
}
cpw_localhost_windowinfo( window );
info->id = (uint_16)window->id;
info->x = (uint_16)window->x;
info->y = (uint_16)window->y;
info->width = (uint_16)window->width;
info->height = (uint_16)window->height;
info->fullscreen = window->fullscreen;
if ( window->id == cpw->win_foregroundid )
info->foreground = true;
else
info->foreground = false;
return true;
}
/*************************************************************************/
/* */
/* user window context */
/* */
/*************************************************************************/
/* The user context can contain anything. It is stored as a void* pointer
in the window context. */
/* set the context for a particular window */
bool cpwSetWindowUserdata( pCpw cpw, pVoid userdata, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
window->userdata = userdata;
return true;
}
/* retrieve the context for a particular window */
pVoid cpwGetWindowUserdata( pCpw cpw, uint_32 id )
{
pCpwWin window = cpw_windowlist_lookup( cpw, id );
if ( window == 0 ) {
cpw_error_set( cpw, cpw_error_invalidwindowid );
return false;
}
return window->userdata;
}