X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fblackberry%2Ffg_main_blackberry.c;h=07ec16cbe2833fc3c6dfcf9ccfefb0d1e434a8c9;hb=c9c91332b9c0908c943cc10fa5ad073df6f3434e;hp=6d2d03c7308fd93ce98ad2a507adb021e032c53a;hpb=4af25b80ace1e391f8886771bdf16c1db2a850f6;p=freeglut diff --git a/src/blackberry/fg_main_blackberry.c b/src/blackberry/fg_main_blackberry.c index 6d2d03c..07ec16c 100644 --- a/src/blackberry/fg_main_blackberry.c +++ b/src/blackberry/fg_main_blackberry.c @@ -31,15 +31,33 @@ #include "fg_internal.h" #include "egl/fg_window_egl.h" +#ifdef NDEBUG +#define LOGI(...) +#endif + +#ifdef __PLAYBOOK__ +#include +#ifndef LOGI +#define LOGI(...) ((void)slogf(1337, _SLOG_INFO, __VA_ARGS__)) +#endif +#define LOGW(...) ((void)slogf(1337, _SLOG_WARNING, __VA_ARGS__)) +#ifndef SLOG2_FA_SIGNED +#define SLOG2_FA_SIGNED(x) (x) +#endif +#else #include +#ifndef LOGI #define LOGI(...) ((void)slog2fa(NULL, 1337, SLOG2_INFO, __VA_ARGS__, SLOG2_FA_END)) +#endif #define LOGW(...) ((void)slog2fa(NULL, 1337, SLOG2_WARNING, __VA_ARGS__, SLOG2_FA_END)) +#endif #include #include #include #include #include #include +#include extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify); extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify); @@ -53,9 +71,12 @@ extern void fgPlatformIconifyWindow( SFG_Window *window ); extern void fgPlatformShowWindow( SFG_Window *window ); extern void fgPlatformMainLoopPostWork ( void ); extern void fgPlatformRotateWindow( SFG_Window *window, int rotation ); +extern void fgPlatformFlushCommands ( void ); static struct touchscreen touchscreen; +#define ESCAPE_BUTTON_KEY 0x001B + unsigned int key_special(int qnxKeycode) { switch(qnxKeycode) { @@ -135,7 +156,7 @@ unsigned char key_ascii(int qnxKeycode) case KEYCODE_RETURN: return 0x000A; case KEYCODE_ESCAPE: - return 0x001B; + return ESCAPE_BUTTON_KEY; } } return qnxKeycode; @@ -161,8 +182,8 @@ fg_time_t fgPlatformSystemTime ( void ) */ void fgPlatformSleepForEvents( fg_time_t msec ) { - //XXX: Is this right? Is there a more direct way to access the context? - if(fgStructure.CurrentWindow && fgDisplay.pDisplay.event == NULL && bps_get_event(&fgDisplay.pDisplay.event, (int)msec) != BPS_SUCCESS) { + if(fgStructure.CurrentWindow && fgDisplay.pDisplay.event == NULL && + bps_get_event(&fgDisplay.pDisplay.event, (int)msec) != BPS_SUCCESS) { LOGW("BPS couldn't get event"); } } @@ -265,6 +286,57 @@ int fgPlatformGetModifiers (int mod) ((mod & KEYMOD_ALT) ? GLUT_ACTIVE_ALT : 0)); } +void fgPlatformHandleKeyboardHeight(SFG_Window* window, int height) +{ + int size[2]; + int screenHeight; + int nScreenHeight = -1; + + screenHeight = glutGet(GLUT_WINDOW_HEIGHT); //Using this takes rotation into account + if(height == 0) { + nScreenHeight = screenHeight; + } + else if(!screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_POSITION, size)) { + /* Calculate the new screen size */ //XXX Make sure to use display size instead of screen size + nScreenHeight = ((size[1] + screenHeight) - height) - size[1]; + } + + if(nScreenHeight != -1) { + /* If nScreenHeight is less then zero then window is covered. If nScreenHeight == height, then no change in size. Else, change in size */ + + int screenWidth = glutGet(GLUT_WINDOW_WIDTH); + if(nScreenHeight < 0) { + LOGI("fgPlatformHandleKeyboardHeight: Covered window state"); + window->State.Visible = GL_FALSE; + window->State.pWState.windowCovered = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_COVERED)); + fghOnReshapeNotify(window, screenWidth, 0, GL_FALSE); + } else { + if(window->State.pWState.windowCovered == GL_TRUE) { + LOGI("fgPlatformHandleKeyboardHeight: Resetting window state"); + + /* Reset window status if it was previously covered */ + switch(window->State.pWState.windowState) { + case NAVIGATOR_WINDOW_FULLSCREEN: + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_FULLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_THUMBNAIL: + window->State.Visible = GL_TRUE; + INVOKE_WCB(*window, WindowStatus, (GLUT_PARTIALLY_RETAINED)); + break; + case NAVIGATOR_WINDOW_INVISIBLE: + window->State.Visible = GL_FALSE; + INVOKE_WCB(*window, WindowStatus, (GLUT_HIDDEN)); + break; + } + window->State.pWState.windowCovered = GL_FALSE; + } + fghOnReshapeNotify(window, screenWidth, nScreenHeight, GL_FALSE); + } + } +} + void fgPlatformProcessSingleEvent ( void ) { if(fgStructure.CurrentWindow == NULL) { @@ -281,6 +353,12 @@ void fgPlatformProcessSingleEvent ( void ) do { SFG_Window* window = fgStructure.CurrentWindow; +#ifdef __PLAYBOOK__ + /* Get the keyboard height before doing anything since we otherwise don't get it until it changes */ + if(window->State.pWState.keyboardHeight == 0) { + virtualkeyboard_get_height(&window->State.pWState.keyboardHeight); + } +#endif domain = bps_event_get_domain(fgDisplay.pDisplay.event); if (domain == screen_get_domain()) { int eventType; @@ -296,7 +374,11 @@ void fgPlatformProcessSingleEvent ( void ) { mtouch_event_t touchEvent; screen_get_mtouch_event(screenEvent, &touchEvent, 0); +#ifndef __PLAYBOOK__ screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod); +#else + mod = 0; +#endif 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)); @@ -338,14 +420,18 @@ void fgPlatformProcessSingleEvent ( void ) // 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); +#ifndef __PLAYBOOK__ screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel); screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_MODIFIERS, &mod); +#else + wheel = mod = 0; +#endif 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? + //XXX Is multitouch be handled in a good way? /* Remember the current modifiers state so user can query it from their callback */ fgState.Modifiers = fgPlatformGetModifiers(mod); @@ -493,34 +579,43 @@ void fgPlatformProcessSingleEvent ( void ) break; } } else if (domain == navigator_get_domain()) { - int eventType = bps_event_get_code(fgDisplay.pDisplay.event); + unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event); switch (eventType) { case NAVIGATOR_WINDOW_STATE: { LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE"); + + /* Covered only happens due to keyboard. When the app is minimized, the keyboard is closed. + When the keyboard is open, and the app is fullscreened, the keyboard is also closed. + If a window is covered and the app is minimized, the state will be set and the keyboard event + will adjust the screen size and change window status. */ navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event); - switch (state) + if(window->State.pWState.windowCovered == GL_FALSE) { - 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; + 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)); + break; + default: + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_WINDOW_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state)); + break; + } } + window->State.pWState.windowState = state; break; } @@ -537,6 +632,8 @@ void fgPlatformProcessSingleEvent ( void ) } else { LOGW("NAVIGATOR_EXIT: No current window"); } + + //XXX Should this be a bit more "forceful" so that it doesn't continue to loop through events? break; } @@ -556,6 +653,11 @@ void fgPlatformProcessSingleEvent ( void ) window->State.pWState.newWidth = 0; window->State.pWState.newHeight = 0; +#ifdef __PLAYBOOK__ + /* On rotation, the keyboard is closed. This prevents two resize calls */ + window->State.pWState.keyboardOpen = GL_FALSE; +#endif + /* Notify that we want to rotate */ navigator_orientation_check_response(fgDisplay.pDisplay.event, true); break; @@ -563,8 +665,16 @@ void fgPlatformProcessSingleEvent ( void ) case NAVIGATOR_ORIENTATION: LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION"); + /* NAVIGATOR_ORIENTATION occurs before NAVIGATOR_KEYBOARD_POSITION */ + /* Rotate and resize the window */ fgPlatformRotateWindow(window, navigator_event_get_orientation_angle(fgDisplay.pDisplay.event)); + fgPlatformFlushCommands(); +#ifdef __PLAYBOOK__ + /* PlayBook doesn't indicate what the new size will be, so we need to retrieve it from the window itself */ + window->State.pWState.newWidth = glutGet(GLUT_WINDOW_WIDTH); + window->State.pWState.newHeight = glutGet(GLUT_WINDOW_HEIGHT); +#endif fghOnReshapeNotify(window, window->State.pWState.newWidth, window->State.pWState.newHeight, GL_FALSE); /* Reset sizes */ @@ -576,7 +686,9 @@ void fgPlatformProcessSingleEvent ( void ) break; case NAVIGATOR_BACK: - /* XXX Should this be a Special/SpecialUp event? */ + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_BACK"); + INVOKE_WCB(*window, Keyboard, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY)); + INVOKE_WCB(*window, KeyboardUp, (ESCAPE_BUTTON_KEY, window->State.MouseX, window->State.MouseY)); break; case NAVIGATOR_WINDOW_ACTIVE: @@ -591,17 +703,53 @@ void fgPlatformProcessSingleEvent ( void ) case NAVIGATOR_ORIENTATION_DONE: case NAVIGATOR_ORIENTATION_RESULT: - LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE\NAVIGATOR_ORIENTATION_RESULT"); + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_ORIENTATION_DONE/NAVIGATOR_ORIENTATION_RESULT"); break; +#ifndef __PLAYBOOK__ case NAVIGATOR_KEYBOARD_STATE: - /* XXX Should something be done with this? */ + { + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_STATE"); + + navigator_keyboard_state_t state = navigator_event_get_keyboard_state(fgDisplay.pDisplay.event); + switch (state) + { + case NAVIGATOR_KEYBOARD_CLOSED: + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_STATE-NAVIGATOR_KEYBOARD_CLOSED"); + /* NAVIGATOR_KEYBOARD_POSITION only occurs on open, so on keyboard close we need to reset the keyboard height */ + fgPlatformHandleKeyboardHeight(window, 0); + break; + case NAVIGATOR_KEYBOARD_OPENING: + case NAVIGATOR_KEYBOARD_OPENED: + case NAVIGATOR_KEYBOARD_CLOSING: + break; + case NAVIGATOR_KEYBOARD_UNRECOGNIZED: + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_STATE-NAVIGATOR_KEYBOARD_UNRECOGNIZED"); + break; + default: + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_STATE unknown: 0x%X", SLOG2_FA_SIGNED(state)); + 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 */ + { + /* Occurs only when keyboard has opened or resizes */ + LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_POSITION"); + + int keyboardOffset = navigator_event_get_keyboard_position(fgDisplay.pDisplay.event); + if(keyboardOffset == BPS_FAILURE) { + LOGW("fgPlatformProcessSingleEvent: NAVIGATOR_KEYBOARD_POSITION: getting keyboard offset failed"); + } else { + /* keyboardOffset is the offset from the top of the screen to the top of the keyboard, AKA the size of the uncovered screen + We want the height of the keyboard. So instead of determining the orientation, getting the right display size, and subtracting; + we just get the keyboard height which may be slower but easier to understand and work with */ + virtualkeyboard_get_height(&keyboardOffset); + fgPlatformHandleKeyboardHeight(window, keyboardOffset); + } break; + } case NAVIGATOR_DEVICE_LOCK_STATE: break; @@ -614,7 +762,7 @@ void fgPlatformProcessSingleEvent ( void ) 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 */ + seems like it doesn't work when the app comes to the foreground. Might be a bug */ break; case NAVIGATOR_ORIENTATION_SIZE: @@ -624,6 +772,7 @@ void fgPlatformProcessSingleEvent ( void ) 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; +#endif case 0: //Doesn't exist in header, but shows up when keyboard shows and resizes break; @@ -633,6 +782,41 @@ void fgPlatformProcessSingleEvent ( void ) break; } } +#ifdef __PLAYBOOK__ + /* While this could be used for non-PlayBook, BlackBerry 10 will still get navigator events, so use those. They are a bit more exact. */ + else if(domain == virtualkeyboard_get_domain()) { + unsigned int eventType = bps_event_get_code(fgDisplay.pDisplay.event); + switch (eventType) { + case VIRTUALKEYBOARD_EVENT_VISIBLE: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_VISIBLE"); + if(window->State.pWState.keyboardOpen != GL_TRUE) { + window->State.pWState.keyboardOpen = GL_TRUE; + fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight); + } + break; + + case VIRTUALKEYBOARD_EVENT_HIDDEN: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_HIDDEN"); + if(window->State.pWState.keyboardOpen != GL_FALSE) { + window->State.pWState.keyboardOpen = GL_FALSE; + fgPlatformHandleKeyboardHeight(window, 0); + } + break; + + case VIRTUALKEYBOARD_EVENT_INFO: + LOGI("fgPlatformProcessSingleEvent: VIRTUALKEYBOARD_EVENT_INFO"); + window->State.pWState.keyboardHeight = virtualkeyboard_event_get_height(fgDisplay.pDisplay.event); + if(window->State.pWState.keyboardOpen == GL_TRUE) { + fgPlatformHandleKeyboardHeight(window, window->State.pWState.keyboardHeight); + } + break; + + default: + LOGW("fgPlatformProcessSingleEvent: unknown virtualkeyboard event: 0x%X", eventType); + break; + } + } +#endif } while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL); /* Reset event to reduce chances of triggering something */ @@ -649,6 +833,11 @@ void fgPlatformMainLoopPreliminaryWork ( void ) /* Allow rotation */ navigator_rotation_lock(false); +#ifdef __PLAYBOOK__ + /* Request keyboard events */ + virtualkeyboard_request_events(0); +#endif + /* Request window events */ screen_request_events(fgDisplay.pDisplay.screenContext); } @@ -660,7 +849,9 @@ void fgPlatformMainLoopPostWork ( void ) /* Stop all events */ screen_stop_events(fgDisplay.pDisplay.screenContext); +#ifndef __PLAYBOOK__ navigator_stop_events(0); +#endif } /* deal with work list items */