Added support for rotation so an app can be rotated and FG will resize and manage the window in the background Additional documentation explaining why certain functions are implemented in the manner they are Changed QNX macro to a non deprecated one

git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@1670 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
dcnieho 2014-01-24 10:33:57 +00:00
parent b817a1d976
commit eb835cc833
6 changed files with 414 additions and 284 deletions

View File

@ -32,9 +32,6 @@ John Tsiombikas <nuclear@member.fsf.org>
Sylvain Beucler Sylvain Beucler
support for Android, X11/EGL, OpenGL(ES) 2.x, misc fixes support for Android, X11/EGL, OpenGL(ES) 2.x, misc fixes
Vincent Simonetti
support for BlackBerry
Diederick C. Niehorster Diederick C. Niehorster
Chris Marshall Chris Marshall
Clive McCarthy Clive McCarthy
@ -42,4 +39,7 @@ Eero Pajarre
Florian Echtler Florian Echtler
Matti Lehtonen Matti Lehtonen
Vincent Simonetti
support for BlackBerry
...and all the opengl-gamedev-l people that made Pawel start this project :) ...and all the opengl-gamedev-l people that made Pawel start this project :)

View File

@ -119,6 +119,9 @@ IF(WIN32)
ENDIF() ENDIF()
ELSEIF(ANDROID OR BLACKBERRY) ELSEIF(ANDROID OR BLACKBERRY)
# BlackBerry and Android share some similar design concepts and ideas, as with many mobile devices.
# As such, some classes can be shared between the two. XXX: Possibly rename shareable classes to
# a more generic name. *_stub? *_mobile?
LIST(APPEND FREEGLUT_SRCS LIST(APPEND FREEGLUT_SRCS
src/android/fg_cursor_android.c src/android/fg_cursor_android.c
src/android/fg_ext_android.c src/android/fg_ext_android.c

View File

@ -113,7 +113,8 @@ struct tagSFG_PlatformJoystick
typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
struct tagSFG_PlatformWindowState struct tagSFG_PlatformWindowState
{ {
char unused; int newWidth;
int newHeight;
}; };
/* Menu font and color definitions */ /* Menu font and color definitions */

View File

@ -52,6 +52,7 @@ extern void fgPlatformHideWindow( SFG_Window *window );
extern void fgPlatformIconifyWindow( SFG_Window *window ); extern void fgPlatformIconifyWindow( SFG_Window *window );
extern void fgPlatformShowWindow( SFG_Window *window ); extern void fgPlatformShowWindow( SFG_Window *window );
extern void fgPlatformMainLoopPostWork ( void ); extern void fgPlatformMainLoopPostWork ( void );
extern void fgPlatformRotateWindow( SFG_Window *window, int rotation );
static struct touchscreen touchscreen; static struct touchscreen touchscreen;
@ -272,320 +273,364 @@ void fgPlatformProcessSingleEvent ( void )
return; return;
} }
if(fgDisplay.pDisplay.event == NULL)
/* Nothing to do */
return;
int domain; int domain;
do do
{ {
if(fgDisplay.pDisplay.event != NULL) { SFG_Window* window = fgStructure.CurrentWindow;
SFG_Window* window = fgStructure.CurrentWindow; domain = bps_event_get_domain(fgDisplay.pDisplay.event);
if (window->Window.Handle != NULL) { if (domain == screen_get_domain()) {
int size[2]; int eventType;
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); int mod;
fghOnReshapeNotify(window,size[0],size[1],GL_FALSE); screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event);
} screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType);
switch (eventType) {
domain = bps_event_get_domain(fgDisplay.pDisplay.event); //Mostly from fg_main_android
if (domain == screen_get_domain()) { case SCREEN_EVENT_MTOUCH_TOUCH:
int eventType; case SCREEN_EVENT_MTOUCH_RELEASE:
int mod; case SCREEN_EVENT_MTOUCH_MOVE:
screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event); {
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType); mtouch_event_t touchEvent;
switch (eventType) { screen_get_mtouch_event(screenEvent, &touchEvent, 0);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
//Mostly from fg_main_android LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_MTOUCH_*: Type: 0x%X, X: %d, Y: %d, Contact Id: %d, Mod: 0x%X", SLOG2_FA_SIGNED(eventType), SLOG2_FA_SIGNED(touchEvent.x), SLOG2_FA_SIGNED(touchEvent.y), SLOG2_FA_SIGNED(touchEvent.contact_id), SLOG2_FA_SIGNED(mod));
case SCREEN_EVENT_MTOUCH_TOUCH:
case SCREEN_EVENT_MTOUCH_RELEASE:
case SCREEN_EVENT_MTOUCH_MOVE:
{
mtouch_event_t touchEvent;
screen_get_mtouch_event(screenEvent, &touchEvent, 0);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_MTOUCH_*: Type: 0x%X, X: %d, Y: %d, Contact Id: %d, Mod: 0x%X", SLOG2_FA_SIGNED(eventType), SLOG2_FA_SIGNED(touchEvent.x), SLOG2_FA_SIGNED(touchEvent.y), SLOG2_FA_SIGNED(touchEvent.contact_id), SLOG2_FA_SIGNED(mod)); /* Remember the current modifiers state so user can query it from their callback */
fgState.Modifiers = fgPlatformGetModifiers(mod);
/* Remember the current modifiers state so user can query it from their callback */ if(touchEvent.contact_id == 0) {
fgState.Modifiers = fgPlatformGetModifiers(mod);
if(touchEvent.contact_id == 0) {
int size[2];
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
handle_left_mouse(touchEvent.x, touchEvent.y, size[1], eventType, window);
}
//Now handle mutlitouch (adapted from fg_main_windows)
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH) {
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_ENTERED ) );
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_DOWN ) );
} else if (eventType == SCREEN_EVENT_MTOUCH_MOVE) {
INVOKE_WCB( *window, MultiMotion, ( touchEvent.contact_id, touchEvent.x, touchEvent.y ) );
//XXX No motion is performed without contact, thus MultiPassive is never used
} else if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) {
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_UP ) );
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_LEFT ) );
}
fgState.Modifiers = INVALID_MODIFIERS;
break;
}
case SCREEN_EVENT_POINTER:
{
//Based off/part taken from GamePlay3d PlatformBlackBerry
static int mouse_pressed = 0;
int buttons;
int position[2];
int wheel;
// A move event will be fired unless a button state changed.
bool move = true;
bool left_move = false;
// This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
int size[2]; int size[2];
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
handle_left_mouse(touchEvent.x, touchEvent.y, size[1], eventType, window);
}
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_POINTER: Buttons: 0x%X, X: %d, Y: %d, Wheel: %d, Mod: 0x%X", SLOG2_FA_SIGNED(buttons), SLOG2_FA_SIGNED(position[0]), SLOG2_FA_SIGNED(position[1]), SLOG2_FA_SIGNED(wheel), SLOG2_FA_SIGNED(mod)); //Now handle mutlitouch (adapted from fg_main_windows)
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH) {
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_ENTERED ) );
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_DOWN ) );
} else if (eventType == SCREEN_EVENT_MTOUCH_MOVE) {
INVOKE_WCB( *window, MultiMotion, ( touchEvent.contact_id, touchEvent.x, touchEvent.y ) );
//XXX No motion is performed without contact, thus MultiPassive is never used
} else if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) {
INVOKE_WCB( *window, MultiButton, ( touchEvent.contact_id, touchEvent.x, touchEvent.y, 0, GLUT_UP ) );
INVOKE_WCB( *window, MultiEntry, ( touchEvent.contact_id, GLUT_LEFT ) );
}
//XXX Should multitouch be handled? fgState.Modifiers = INVALID_MODIFIERS;
break;
}
case SCREEN_EVENT_POINTER:
{
//Based off/part taken from GamePlay3d PlatformBlackBerry
static int mouse_pressed = 0;
int buttons;
int position[2];
int wheel;
// A move event will be fired unless a button state changed.
bool move = true;
bool left_move = false;
// This is a mouse move event, it is applicable to a device with a usb mouse or simulator.
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
int size[2];
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_POINTER: Buttons: 0x%X, X: %d, Y: %d, Wheel: %d, Mod: 0x%X", SLOG2_FA_SIGNED(buttons), SLOG2_FA_SIGNED(position[0]), SLOG2_FA_SIGNED(position[1]), SLOG2_FA_SIGNED(wheel), SLOG2_FA_SIGNED(mod));
//XXX Should multitouch be handled?
/* Remember the current modifiers state so user can query it from their callback */
fgState.Modifiers = fgPlatformGetModifiers(mod);
// Handle left mouse. Interpret as touch if the left mouse event is not consumed.
if (buttons & SCREEN_LEFT_MOUSE_BUTTON) {
if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) {
left_move = true;
} else {
move = false;
mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_TOUCH, window);
}
} else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) {
move = false;
mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON;
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_RELEASE, window);
}
// Handle right mouse.
if (buttons & SCREEN_RIGHT_MOUSE_BUTTON) {
if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0) {
move = false;
mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_DOWN, position[0], position[1]));
}
} else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) {
move = false;
mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_UP, position[0], position[1]));
}
// Handle middle mouse.
if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) {
if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) {
move = false;
mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_DOWN, position[0], position[1]));
}
} else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) {
move = false;
mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_UP, position[0], position[1]));
}
// Fire a move event if none of the buttons changed.
if (left_move || move) {
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_MOVE, window);
}
if (wheel) {
/* Very slightly modified from fg_main_mswin.
* Because we don't want MouseWheel to be called every. single. time.
* That the action occurs, we mimic the Windows version with "wheel deltas"
* XXX Do we even want this?
* XXX If we want this, it's possible to get horizontal scroll as well.
* XXX -Vertical scroll=wheel 0, horizontal=wheel 1? */
fgState.MouseWheelTicks -= wheel;
if (abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
{
int wheel_number = 0;
int direction = (fgState.MouseWheelTicks > 0) ? -1 : 1;
if (!FETCH_WCB(*window, MouseWheel) && !FETCH_WCB(*window, Mouse))
break;
//XXX fgSetWindow(window);
while(abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
{
if (FETCH_WCB(*window, MouseWheel))
INVOKE_WCB(*window, MouseWheel, (wheel_number, direction, window->State.MouseX, window->State.MouseY));
else /* No mouse wheel, call the mouse button callback twice */
{
/*
* Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
* " " one +1 to 5, -1 to 6, ...
*
* XXX The below assumes that you have no more than 3 mouse
* XXX buttons. Sorry.
*/
int button = wheel_number * 2 + 3;
if (direction < 0)
++button;
INVOKE_WCB(*window, Mouse, (button, GLUT_DOWN, window->State.MouseX, window->State.MouseY));
INVOKE_WCB(*window, Mouse, (button, GLUT_UP, window->State.MouseX, window->State.MouseY));
}
fgState.MouseWheelTicks -= WHEEL_DELTA * direction;
}
}
}
fgState.Modifiers = INVALID_MODIFIERS;
break;
}
//Based off fg_main_android
case SCREEN_EVENT_KEYBOARD:
{
int flags;
int value;
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Flags: 0x%X, Sym: 0x%X, Mod: 0x%X", SLOG2_FA_SIGNED(flags), SLOG2_FA_SIGNED(value), SLOG2_FA_SIGNED(mod));
/* Suppress key repeats if desired. Based off fg_main_mswin */
if ((flags & KEY_REPEAT) == 0 || (fgState.KeyRepeat == GLUT_KEY_REPEAT_OFF && fgStructure.CurrentWindow->State.IgnoreKeyRepeat == GL_TRUE)) {
unsigned int keypress = 0;
unsigned char ascii = 0;
/* Remember the current modifiers state so user can query it from their callback */ /* Remember the current modifiers state so user can query it from their callback */
fgState.Modifiers = fgPlatformGetModifiers(mod); fgState.Modifiers = fgPlatformGetModifiers(mod);
// Handle left mouse. Interpret as touch if the left mouse event is not consumed. /* Process keys */
if (buttons & SCREEN_LEFT_MOUSE_BUTTON) { if ((keypress = key_special(value))) {
if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) { if(flags & KEY_DOWN) {
left_move = true; INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY));
} else { } else {
move = false; INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY));
mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_TOUCH, window);
} }
} else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON) { } else if((flags & KEY_SYM_VALID) && (ascii = key_ascii(value))) {
move = false; if(flags & KEY_DOWN) {
mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON; INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY));
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_RELEASE, window); } else {
} INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY));
// Handle right mouse.
if (buttons & SCREEN_RIGHT_MOUSE_BUTTON) {
if ((mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) == 0) {
move = false;
mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_DOWN, position[0], position[1]));
}
} else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON) {
move = false;
mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_RIGHT_BUTTON, GLUT_UP, position[0], position[1]));
}
// Handle middle mouse.
if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) {
if ((mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) {
move = false;
mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_DOWN, position[0], position[1]));
}
} else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON) {
move = false;
mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
INVOKE_WCB(*window, Mouse, (GLUT_MIDDLE_BUTTON, GLUT_UP, position[0], position[1]));
}
// Fire a move event if none of the buttons changed.
if (left_move || move) {
handle_left_mouse(position[0], position[1], size[1], SCREEN_EVENT_MTOUCH_MOVE, window);
}
if (wheel) {
/* Very slightly modified from fg_main_mswin.
* Because we don't want MouseWheel to be called every. single. time.
* That the action occurs, we mimic the Windows version with "wheel deltas"
* XXX Do we even want this?
* XXX If we want this, it's possible to get horizontal scroll as well.
* XXX -Vertical scroll=wheel 0, horizontal=wheel 1? */
fgState.MouseWheelTicks -= wheel;
if (abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
{
int wheel_number = 0;
int direction = (fgState.MouseWheelTicks > 0) ? -1 : 1;
if (!FETCH_WCB(*window, MouseWheel) && !FETCH_WCB(*window, Mouse))
break;
//XXX fgSetWindow(window);
while(abs(fgState.MouseWheelTicks) >= WHEEL_DELTA)
{
if (FETCH_WCB(*window, MouseWheel))
INVOKE_WCB(*window, MouseWheel, (wheel_number, direction, window->State.MouseX, window->State.MouseY));
else /* No mouse wheel, call the mouse button callback twice */
{
/*
* Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
* " " one +1 to 5, -1 to 6, ...
*
* XXX The below assumes that you have no more than 3 mouse
* XXX buttons. Sorry.
*/
int button = wheel_number * 2 + 3;
if (direction < 0)
++button;
INVOKE_WCB(*window, Mouse, (button, GLUT_DOWN, window->State.MouseX, window->State.MouseY));
INVOKE_WCB(*window, Mouse, (button, GLUT_UP, window->State.MouseX, window->State.MouseY));
}
fgState.MouseWheelTicks -= WHEEL_DELTA * direction;
}
} }
} else {
LOGW("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Unhandled key event");
} }
fgState.Modifiers = INVALID_MODIFIERS; fgState.Modifiers = INVALID_MODIFIERS;
break;
} }
break;
}
//Based off fg_main_android case SCREEN_EVENT_PROPERTY:
case SCREEN_EVENT_KEYBOARD: case SCREEN_EVENT_IDLE:
break;
default:
LOGW("fgPlatformProcessSingleEvent: unknown screen event: 0x%X", SLOG2_FA_SIGNED(eventType));
break;
}
} else if (domain == navigator_get_domain()) {
int eventType = bps_event_get_code(fgDisplay.pDisplay.event);
switch (eventType) {
case NAVIGATOR_WINDOW_STATE:
{
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE");
navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event);
switch (state)
{ {
int flags; case NAVIGATOR_WINDOW_FULLSCREEN:
int value; LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN");
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags); window->State.Visible = GL_TRUE;
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_SYM, &value); INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED));
screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Flags: 0x%X, Sym: 0x%X, Mod: 0x%X", SLOG2_FA_SIGNED(flags), SLOG2_FA_SIGNED(value), SLOG2_FA_SIGNED(mod));
/* Suppress key repeats if desired. Based off fg_main_mswin */
if ((flags & KEY_REPEAT) == 0 || (fgState.KeyRepeat == GLUT_KEY_REPEAT_OFF && fgStructure.CurrentWindow->State.IgnoreKeyRepeat == GL_TRUE)) {
unsigned int keypress = 0;
unsigned char ascii = 0;
/* Remember the current modifiers state so user can query it from their callback */
fgState.Modifiers = fgPlatformGetModifiers(mod);
/* Process keys */
if ((keypress = key_special(value))) {
if(flags & KEY_DOWN) {
INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY));
} else {
INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY));
}
} else if((flags & KEY_SYM_VALID) && (ascii = key_ascii(value))) {
if(flags & KEY_DOWN) {
INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY));
} else {
INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY));
}
} else {
LOGW("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Unhandled key event");
}
fgState.Modifiers = INVALID_MODIFIERS;
}
break; break;
} case NAVIGATOR_WINDOW_THUMBNAIL:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_THUMBNAIL");
case SCREEN_EVENT_PROPERTY: window->State.Visible = GL_TRUE;
case SCREEN_EVENT_IDLE: INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED));
break;
case NAVIGATOR_WINDOW_INVISIBLE:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_INVISIBLE");
window->State.Visible = GL_FALSE;
INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN)); //XXX Should this be GLUT_FULLY_COVERED?
break; break;
default: default:
LOGW("fgPlatformProcessSingleEvent: unknown screen event: 0x%X", SLOG2_FA_SIGNED(eventType)); LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state));
break; break;
} }
} else if (domain == navigator_get_domain()) { break;
int eventType = bps_event_get_code(fgDisplay.pDisplay.event); }
switch (eventType) {
case NAVIGATOR_WINDOW_STATE: case NAVIGATOR_EXIT:
{ {
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE"); LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT");
navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event);
switch (state) fgPlatformMainLoopPostWork();
{
case NAVIGATOR_WINDOW_FULLSCREEN: /* User closed the application for good, let's kill the window */
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN"); SFG_Window* window = fgStructure.CurrentWindow;
window->State.Visible = GL_TRUE; if (window != NULL) {
INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); fgDestroyWindow(window);
break; } else {
case NAVIGATOR_WINDOW_THUMBNAIL: LOGW("NAVIGATOR_EXIT: No current window");
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_THUMBNAIL");
window->State.Visible = GL_TRUE;
INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED));
break;
case NAVIGATOR_WINDOW_INVISIBLE:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_INVISIBLE");
window->State.Visible = GL_FALSE;
INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN)); //XXX Should this be GLUT_FULLY_COVERED?
break;
default:
LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state));
break;
}
break;
} }
break;
}
case NAVIGATOR_EXIT: case NAVIGATOR_SWIPE_DOWN:
{ /* XXX Open app menu */
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT"); break;
fgPlatformMainLoopPostWork(); /* Orientation is a bunch of handshakes.
- First the app get's asked if it wants to rotate (NAVIGATOR_ORIENTATION_CHECK)
- If the app wants to rotate, then it will be told what size it will be after rotate (NAVIGATOR_ORIENTATION_SIZE).
- Once the OS confirms that it's ready to rotate, it tells the app to handle rotation (NAVIGATOR_ORIENTATION).
- Once rotation is complete, the OS tells the app it's done (NAVIGATOR_ORIENTATION_DONE) */
case NAVIGATOR_ORIENTATION_CHECK:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_CHECK");
/* User closed the application for good, let's kill the window */ /* Reset sizes */
SFG_Window* window = fgStructure.CurrentWindow; window->State.pWState.newWidth = 0;
if (window != NULL) { window->State.pWState.newHeight = 0;
fgDestroyWindow(window);
} else {
LOGW("NAVIGATOR_EXIT: No current window");
}
break;
}
case NAVIGATOR_SWIPE_DOWN: /* Notify that we want to rotate */
/* XXX Open app menu */ navigator_orientation_check_response(fgDisplay.pDisplay.event, true);
break; break;
case NAVIGATOR_BACK: case NAVIGATOR_ORIENTATION:
/* XXX Should this be a Special/SpecialUp event? */ LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION");
break;
case NAVIGATOR_WINDOW_ACTIVE: /* Rotate and resize the window */
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE"); fgPlatformRotateWindow(window, navigator_event_get_orientation_angle(fgDisplay.pDisplay.event));
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME)); fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE);
break;
case NAVIGATOR_WINDOW_INACTIVE: /* Reset sizes */
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE"); window->State.pWState.newWidth = 0;
INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE)); window->State.pWState.newHeight = 0;
break;
case NAVIGATOR_KEYBOARD_STATE: /* Done rotating */
case NAVIGATOR_KEYBOARD_POSITION: navigator_done_orientation(fgDisplay.pDisplay.event);
/* TODO Something needs to be done with this. Not sure what */ break;
break;
case NAVIGATOR_DEVICE_LOCK_STATE: case NAVIGATOR_BACK:
break; /* XXX Should this be a Special/SpecialUp event? */
break;
case NAVIGATOR_WINDOW_COVER: case NAVIGATOR_WINDOW_ACTIVE:
case NAVIGATOR_WINDOW_COVER_ENTER: LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE");
case NAVIGATOR_WINDOW_COVER_EXIT: INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME));
/* BlackBerry specific. Let app status and window status take care of everything */ break;
break;
case NAVIGATOR_APP_STATE: case NAVIGATOR_WINDOW_INACTIVE:
/* Can do the same as NAVIGATOR_WINDOW_ACTIVE/NAVIGATOR_WINDOW_INACTIVE but LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE");
seems less likely to work when the app comes to the foreground. Might be a bug */ INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE));
break; break;
case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes case NAVIGATOR_ORIENTATION_DONE:
break; case NAVIGATOR_ORIENTATION_RESULT:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE\NAVIGATOR_ORIENTATION_RESULT");
break;
default: case NAVIGATOR_KEYBOARD_STATE:
LOGW("fgPlatformProcessSingleEvent: unknown navigator event: 0x%X", SLOG2_FA_SIGNED(eventType)); /* XXX Should something be done with this? */
break; break;
}
case NAVIGATOR_KEYBOARD_POSITION:
/* TODO Invoke resize with the modified screen size (((y + height) - keyboardPos) - y).
* If result is less then zero then window is covered. If == height, then no change in size. Else, change in size */
break;
case NAVIGATOR_DEVICE_LOCK_STATE:
break;
case NAVIGATOR_WINDOW_COVER:
case NAVIGATOR_WINDOW_COVER_ENTER:
case NAVIGATOR_WINDOW_COVER_EXIT:
/* BlackBerry specific. Let app status and window status take care of everything */
break;
case NAVIGATOR_APP_STATE:
/* Can do the same as NAVIGATOR_WINDOW_ACTIVE/NAVIGATOR_WINDOW_INACTIVE but
seems less likely to work when the app comes to the foreground. Might be a bug */
break;
case NAVIGATOR_ORIENTATION_SIZE:
LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_SIZE");
/* Get new window size */
window->State.pWState.newWidth = navigator_event_get_orientation_size_width(fgDisplay.pDisplay.event);
window->State.pWState.newHeight = navigator_event_get_orientation_size_height(fgDisplay.pDisplay.event);
break;
case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes
break;
default:
LOGW("fgPlatformProcessSingleEvent: unknown navigator event: 0x%X", SLOG2_FA_SIGNED(eventType));
break;
} }
} }
} while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL); } while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL);
@ -600,7 +645,9 @@ void fgPlatformMainLoopPreliminaryWork ( void )
/* Request navigator events */ /* Request navigator events */
navigator_request_events(0); navigator_request_events(0);
//XXX rotation lock? navigator_rotation_lock(true);
/* Allow rotation */
navigator_rotation_lock(false);
/* Request window events */ /* Request window events */
screen_request_events(fgDisplay.pDisplay.screenContext); screen_request_events(fgDisplay.pDisplay.screenContext);
@ -610,6 +657,7 @@ void fgPlatformMainLoopPostWork ( void )
{ {
LOGI("fgPlatformMainLoopPostWork"); LOGI("fgPlatformMainLoopPostWork");
/* Stop all events */
screen_stop_events(fgDisplay.pDisplay.screenContext); screen_stop_events(fgDisplay.pDisplay.screenContext);
navigator_stop_events(0); navigator_stop_events(0);
@ -623,6 +671,11 @@ void fgPlatformInitWork(SFG_Window* window)
/* Position callback, always at 0,0 */ /* Position callback, always at 0,0 */
fghOnPositionNotify(window, 0, 0, GL_TRUE); fghOnPositionNotify(window, 0, 0, GL_TRUE);
/* Get window size */
int size[2];
screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
fghOnReshapeNotify(window, size[0], size[1], GL_FALSE);
/* Size gets notified on window creation with size detection in mainloop above /* Size gets notified on window creation with size detection in mainloop above
* XXX CHECK: does this messages happen too early like on windows, * XXX CHECK: does this messages happen too early like on windows,
* so client code cannot have registered a callback yet and the message * so client code cannot have registered a callback yet and the message

View File

@ -58,11 +58,12 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
fgDisplay.pDisplay.single_native_window = sWindow; fgDisplay.pDisplay.single_native_window = sWindow;
/* Set window properties */ /* Set window properties */
int orientation = atoi(getenv("ORIENTATION"));
int screenFormat = SCREEN_FORMAT_RGBA8888; //XXX Should this be determined by config? int screenFormat = SCREEN_FORMAT_RGBA8888; //XXX Should this be determined by config?
#ifdef GL_ES_VERSION_2_0 #ifdef GL_ES_VERSION_2_0
int screenUsage = SCREEN_USAGE_OPENGL_ES2; int screenUsage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION;
#elif GL_VERSION_ES_CM_1_0 || GL_VERSION_ES_CL_1_0 || GL_VERSION_ES_CM_1_1 || GL_VERSION_ES_CL_1_1 #elif GL_VERSION_ES_CM_1_0 || GL_VERSION_ES_CL_1_0 || GL_VERSION_ES_CM_1_1 || GL_VERSION_ES_CL_1_1
int screenUsage = SCREEN_USAGE_OPENGL_ES1; int screenUsage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION;
#endif #endif
#ifndef __X86__ #ifndef __X86__
screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display
@ -78,8 +79,8 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
return; return;
} }
/* Uncomment when multiple windows are supported
int value[2]; int value[2];
/* Uncomment when multiple windows are supported
if(positionUse) { if(positionUse) {
value[0] = x; value[0] = x;
value[1] = y; value[1] = y;
@ -88,17 +89,83 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
fgError("Could not set window position"); fgError("Could not set window position");
return; return;
} }
} }*/
if(sizeUse) { if(sizeUse) {
/* Uncomment when multiple windows are supported
value[0] = w; value[0] = w;
value[1] = h; value[1] = h;
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) { */
//TEMP until ^^ is uncommented
if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
screen_destroy_window(sWindow); screen_destroy_window(sWindow);
fgError("Could not set window buffer size"); fgError("Could not get window mode");
return; return;
} }
}*/ } else {
/* From PlatformBlackBerry in GamePlay3d */
screen_display_t display;
if (screen_get_window_property_pv(sWindow, SCREEN_PROPERTY_DISPLAY, (void**)&display)) {
screen_destroy_window(sWindow);
fgError("Could not get window display");
return;
}
screen_display_mode_t displayMode;
if (screen_get_display_property_pv(display, SCREEN_PROPERTY_MODE, (void**)&displayMode)) {
screen_destroy_window(sWindow);
fgError("Could not get display mode");
return;
}
if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
screen_destroy_window(sWindow);
fgError("Could not get window mode");
return;
}
/* Adjust buffer sizes based on rotation */
if ((orientation == 0) || (orientation == 180))
{
if (((displayMode.width > displayMode.height) && (value[0] < value[1])) ||
((displayMode.width < displayMode.height) && (value[0] > value[1])))
{
int tmp = value[1];
value[1] = value[0];
value[0] = tmp;
}
}
else if ((orientation == 90) || (orientation == 270))
{
if (((displayMode.width > displayMode.height) && (value[0] > value[1])) ||
((displayMode.width < displayMode.height) && (value[0] < value[1])))
{
int tmp = value[1];
value[1] = value[0];
value[0] = tmp;
}
}
else
{
screen_destroy_window(sWindow);
fgError("Unexpected rotation angle");
return;
}
}
/* Set rotation if usage allows it */
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_ROTATION, &orientation)) {
screen_destroy_window(sWindow);
fgError("Could not set window rotation");
return;
}
/* Set buffer sizes */
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
screen_destroy_window(sWindow);
fgError("Could not set window buffer size");
return;
}
/* Create window buffers */ /* Create window buffers */
if (screen_create_window_buffers(sWindow, (fgState.DisplayMode & GLUT_DOUBLE) ? 2 : 1)) { if (screen_create_window_buffers(sWindow, (fgState.DisplayMode & GLUT_DOUBLE) ? 2 : 1)) {
@ -108,7 +175,7 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
} }
/* Save window and set state */ /* Save window and set state */
window->Window.Handle = fgDisplay.pDisplay.single_native_window; window->Window.Handle = sWindow;
window->State.WorkMask |= GLUT_INIT_WORK; window->State.WorkMask |= GLUT_INIT_WORK;
window->State.IsFullscreen = GL_TRUE; //XXX Always fullscreen for now window->State.IsFullscreen = GL_TRUE; //XXX Always fullscreen for now
@ -122,6 +189,11 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title,
window->State.Visible = GL_TRUE; window->State.Visible = GL_TRUE;
} }
void fgPlatformRotateWindow(SFG_Window* window, int rotation)
{
screen_set_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_ROTATION, &rotation);
}
/* /*
* Request a window resize * Request a window resize
*/ */
@ -162,6 +234,7 @@ void fgPlatformHideWindow( SFG_Window *window )
void fgPlatformIconifyWindow( SFG_Window *window ) void fgPlatformIconifyWindow( SFG_Window *window )
{ {
//XXX This is possible via Cascades, but can't seem to find a C-level API //XXX This is possible via Cascades, but can't seem to find a C-level API
//XXX bb::Application::instance()->minimize();
fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n"); fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n");
} }

View File

@ -45,7 +45,7 @@
#elif defined (__ANDROID__) #elif defined (__ANDROID__)
# define TARGET_HOST_ANDROID 1 # define TARGET_HOST_ANDROID 1
#elif defined (__QNX__) #elif defined (__QNXNTO__)
# define TARGET_HOST_BLACKBERRY 1 # define TARGET_HOST_BLACKBERRY 1
#elif defined(__posix__) || defined(__unix__) || defined(__linux__) || defined(__sun) #elif defined(__posix__) || defined(__unix__) || defined(__linux__) || defined(__sun)