From: Rcmaniac25 Date: Fri, 24 Jan 2014 10:33:57 +0000 (+0000) Subject: Added support for rotation so an app can be rotated and FG will resize and manage... X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=4af25b80ace1e391f8886771bdf16c1db2a850f6;p=freeglut 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: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1670 7f0cb862-5218-0410-a997-914c9d46530a --- diff --git a/AUTHORS b/AUTHORS index 972e662..62db946 100644 --- a/AUTHORS +++ b/AUTHORS @@ -32,9 +32,6 @@ John Tsiombikas Sylvain Beucler support for Android, X11/EGL, OpenGL(ES) 2.x, misc fixes -Vincent Simonetti - support for BlackBerry - Diederick C. Niehorster Chris Marshall Clive McCarthy @@ -42,4 +39,7 @@ Eero Pajarre Florian Echtler Matti Lehtonen +Vincent Simonetti + support for BlackBerry + ...and all the opengl-gamedev-l people that made Pawel start this project :) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16661e6..946ac6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,6 +119,9 @@ IF(WIN32) ENDIF() 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 src/android/fg_cursor_android.c src/android/fg_ext_android.c diff --git a/src/blackberry/fg_internal_blackberry.h b/src/blackberry/fg_internal_blackberry.h index 90b11fe..63cca30 100644 --- a/src/blackberry/fg_internal_blackberry.h +++ b/src/blackberry/fg_internal_blackberry.h @@ -113,7 +113,8 @@ struct tagSFG_PlatformJoystick typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState; struct tagSFG_PlatformWindowState { - char unused; + int newWidth; + int newHeight; }; /* Menu font and color definitions */ diff --git a/src/blackberry/fg_main_blackberry.c b/src/blackberry/fg_main_blackberry.c index 71f7b6d..6d2d03c 100644 --- a/src/blackberry/fg_main_blackberry.c +++ b/src/blackberry/fg_main_blackberry.c @@ -52,6 +52,7 @@ extern void fgPlatformHideWindow( SFG_Window *window ); extern void fgPlatformIconifyWindow( SFG_Window *window ); extern void fgPlatformShowWindow( SFG_Window *window ); extern void fgPlatformMainLoopPostWork ( void ); +extern void fgPlatformRotateWindow( SFG_Window *window, int rotation ); static struct touchscreen touchscreen; @@ -272,320 +273,364 @@ void fgPlatformProcessSingleEvent ( void ) return; } + if(fgDisplay.pDisplay.event == NULL) + /* Nothing to do */ + return; + int domain; do { - if(fgDisplay.pDisplay.event != NULL) { - SFG_Window* window = fgStructure.CurrentWindow; - if (window->Window.Handle != NULL) { - int size[2]; - screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size); - fghOnReshapeNotify(window,size[0],size[1],GL_FALSE); - } - - domain = bps_event_get_domain(fgDisplay.pDisplay.event); - if (domain == screen_get_domain()) { - int eventType; - int mod; - screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event); - screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType); - switch (eventType) { - - //Mostly from fg_main_android - 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)); + SFG_Window* window = fgStructure.CurrentWindow; + domain = bps_event_get_domain(fgDisplay.pDisplay.event); + if (domain == screen_get_domain()) { + int eventType; + int mod; + screen_event_t screenEvent = screen_event_get_event(fgDisplay.pDisplay.event); + screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_TYPE, &eventType); + switch (eventType) { + + //Mostly from fg_main_android + 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); - /* Remember the current modifiers state so user can query it from their callback */ - fgState.Modifiers = fgPlatformGetModifiers(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)); - 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); - } + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers(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 ) ); - } + 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); + } - fgState.Modifiers = INVALID_MODIFIERS; - break; + //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 ) ); } - 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); + 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)); + 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? + //XXX Should multitouch be handled? - /* 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 */ + 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) { + // 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_RELEASE, window); + 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) { + // 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_UP, position[0], position[1])); + 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) { + // 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_UP, position[0], position[1])); + 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); - } + // 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 (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; + if (!FETCH_WCB(*window, MouseWheel) && !FETCH_WCB(*window, Mouse)) + break; - //XXX fgSetWindow(window); + //XXX fgSetWindow(window); - while(abs(fgState.MouseWheelTicks) >= WHEEL_DELTA) + 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 */ { - 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; + /* + * 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.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 */ - 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.MouseWheelTicks -= WHEEL_DELTA * direction; } - - fgState.Modifiers = INVALID_MODIFIERS; } - break; } - case SCREEN_EVENT_PROPERTY: - case SCREEN_EVENT_IDLE: - break; + fgState.Modifiers = INVALID_MODIFIERS; + 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) { + //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); - case NAVIGATOR_WINDOW_STATE: - { - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE"); - navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event); - switch (state) - { - case NAVIGATOR_WINDOW_FULLSCREEN: - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN"); - window->State.Visible = GL_TRUE; - INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); - break; - case NAVIGATOR_WINDOW_THUMBNAIL: - 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; - } + 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)); - case NAVIGATOR_EXIT: - { - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT"); + /* 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; - fgPlatformMainLoopPostWork(); + /* Remember the current modifiers state so user can query it from their callback */ + fgState.Modifiers = fgPlatformGetModifiers(mod); - /* User closed the application for good, let's kill the window */ - SFG_Window* window = fgStructure.CurrentWindow; - if (window != NULL) { - fgDestroyWindow(window); + /* 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("NAVIGATOR_EXIT: No current window"); + LOGW("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Unhandled key event"); } - break; - } - case NAVIGATOR_SWIPE_DOWN: - /* XXX Open app menu */ - break; + fgState.Modifiers = INVALID_MODIFIERS; + } + break; + } - case NAVIGATOR_BACK: - /* XXX Should this be a Special/SpecialUp event? */ - break; + case SCREEN_EVENT_PROPERTY: + case SCREEN_EVENT_IDLE: + break; - case NAVIGATOR_WINDOW_ACTIVE: - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE"); - INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME)); - 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_INACTIVE: - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE"); - INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE)); + case NAVIGATOR_WINDOW_STATE: + { + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE"); + navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event); + switch (state) + { + case NAVIGATOR_WINDOW_FULLSCREEN: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_FULLSCREEN"); + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); break; - - case NAVIGATOR_KEYBOARD_STATE: - case NAVIGATOR_KEYBOARD_POSITION: - /* TODO Something needs to be done with this. Not sure what */ + case NAVIGATOR_WINDOW_THUMBNAIL: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE-NAVIGATOR_WINDOW_THUMBNAIL"); + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED)); break; - - case NAVIGATOR_DEVICE_LOCK_STATE: + 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; - - 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 */ + default: + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state)); break; + } + 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_EXIT: + { + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT"); - case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes - break; + fgPlatformMainLoopPostWork(); - default: - LOGW("fgPlatformProcessSingleEvent: unknown navigator event: 0x%X", SLOG2_FA_SIGNED(eventType)); - break; + /* User closed the application for good, let's kill the window */ + SFG_Window* window = fgStructure.CurrentWindow; + if (window != NULL) { + fgDestroyWindow(window); + } else { + LOGW("NAVIGATOR_EXIT: No current window"); } + break; + } + + case NAVIGATOR_SWIPE_DOWN: + /* XXX Open app menu */ + break; + + /* 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"); + + /* Reset sizes */ + window->State.pWState.newWidth = 0; + window->State.pWState.newHeight = 0; + + /* Notify that we want to rotate */ + navigator_orientation_check_response(fgDisplay.pDisplay.event, true); + break; + + case NAVIGATOR_ORIENTATION: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION"); + + /* Rotate and resize the window */ + fgPlatformRotateWindow(window, navigator_event_get_orientation_angle(fgDisplay.pDisplay.event)); + fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE); + + /* Reset sizes */ + window->State.pWState.newWidth = 0; + window->State.pWState.newHeight = 0; + + /* Done rotating */ + navigator_done_orientation(fgDisplay.pDisplay.event); + break; + + case NAVIGATOR_BACK: + /* XXX Should this be a Special/SpecialUp event? */ + break; + + case NAVIGATOR_WINDOW_ACTIVE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_ACTIVE"); + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_RESUME)); + break; + + case NAVIGATOR_WINDOW_INACTIVE: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_INACTIVE"); + INVOKE_WCB(*window, AppStatus, (GLUT_APPSTATUS_PAUSE)); + break; + + case NAVIGATOR_ORIENTATION_DONE: + case NAVIGATOR_ORIENTATION_RESULT: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE\NAVIGATOR_ORIENTATION_RESULT"); + break; + + case NAVIGATOR_KEYBOARD_STATE: + /* XXX Should something be done with this? */ + 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); @@ -600,7 +645,9 @@ void fgPlatformMainLoopPreliminaryWork ( void ) /* Request navigator events */ navigator_request_events(0); - //XXX rotation lock? navigator_rotation_lock(true); + + /* Allow rotation */ + navigator_rotation_lock(false); /* Request window events */ screen_request_events(fgDisplay.pDisplay.screenContext); @@ -610,6 +657,7 @@ void fgPlatformMainLoopPostWork ( void ) { LOGI("fgPlatformMainLoopPostWork"); + /* Stop all events */ screen_stop_events(fgDisplay.pDisplay.screenContext); navigator_stop_events(0); @@ -623,6 +671,11 @@ void fgPlatformInitWork(SFG_Window* window) /* Position callback, always at 0,0 */ 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 * XXX CHECK: does this messages happen too early like on windows, * so client code cannot have registered a callback yet and the message diff --git a/src/blackberry/fg_window_blackberry.c b/src/blackberry/fg_window_blackberry.c index 61bd58d..f18512e 100644 --- a/src/blackberry/fg_window_blackberry.c +++ b/src/blackberry/fg_window_blackberry.c @@ -58,11 +58,12 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, fgDisplay.pDisplay.single_native_window = sWindow; /* Set window properties */ + int orientation = atoi(getenv("ORIENTATION")); int screenFormat = SCREEN_FORMAT_RGBA8888; //XXX Should this be determined by config? #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 - int screenUsage = SCREEN_USAGE_OPENGL_ES1; + int screenUsage = SCREEN_USAGE_OPENGL_ES1 | SCREEN_USAGE_ROTATION; #endif #ifndef __X86__ screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display @@ -78,8 +79,8 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, return; } - /* Uncomment when multiple windows are supported int value[2]; + /* Uncomment when multiple windows are supported if(positionUse) { value[0] = x; value[1] = y; @@ -88,17 +89,83 @@ void fgPlatformOpenWindow( SFG_Window* window, const char* title, fgError("Could not set window position"); return; } - } + }*/ if(sizeUse) { + /* Uncomment when multiple windows are supported value[0] = w; 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); - fgError("Could not set window buffer size"); + fgError("Could not get window mode"); 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 */ 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 */ - window->Window.Handle = fgDisplay.pDisplay.single_native_window; + window->Window.Handle = sWindow; window->State.WorkMask |= GLUT_INIT_WORK; 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; } +void fgPlatformRotateWindow(SFG_Window* window, int rotation) +{ + screen_set_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_ROTATION, &rotation); +} + /* * Request a window resize */ @@ -162,6 +234,7 @@ void fgPlatformHideWindow( 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 bb::Application::instance()->minimize(); fprintf(stderr, "fgPlatformGlutIconifyWindow: STUB\n"); } diff --git a/src/fg_internal.h b/src/fg_internal.h index 4792ad8..6c1060f 100644 --- a/src/fg_internal.h +++ b/src/fg_internal.h @@ -45,7 +45,7 @@ #elif defined (__ANDROID__) # define TARGET_HOST_ANDROID 1 -#elif defined (__QNX__) +#elif defined (__QNXNTO__) # define TARGET_HOST_BLACKBERRY 1 #elif defined(__posix__) || defined(__unix__) || defined(__linux__) || defined(__sun)