Fixed bug where if statement didn't have parenthesis, causing it to just exit
[freeglut] / src / blackberry / fg_main_blackberry.c
index f7b8f66..73b9f41 100644 (file)
@@ -51,6 +51,7 @@ extern void fgPlatformPopWindow( SFG_Window *window );
 extern void fgPlatformHideWindow( SFG_Window *window );
 extern void fgPlatformIconifyWindow( SFG_Window *window );
 extern void fgPlatformShowWindow( SFG_Window *window );
+extern void fgPlatformMainLoopPostWork ( void );
 
 static struct touchscreen touchscreen;
 
@@ -160,7 +161,7 @@ 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(bps_get_event(&fgStructure.CurrentWindow->Window.pContext.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");
     }
 }
@@ -253,26 +254,40 @@ void handle_left_mouse(int x, int y, int height, int eventType, SFG_Window* wind
     }
 }
 
+/*
+ * Determine a GLUT modifier mask based on BlackBerry modifier info.
+ */
+int fgPlatformGetModifiers (int mod)
+{
+    return (((mod & KEYMOD_SHIFT) ? GLUT_ACTIVE_SHIFT : 0) |
+            ((mod & KEYMOD_CTRL) ? GLUT_ACTIVE_CTRL : 0) |
+            ((mod & KEYMOD_ALT) ? GLUT_ACTIVE_ALT : 0));
+}
+
 void fgPlatformProcessSingleEvent ( void )
 {
+    if(fgStructure.CurrentWindow == NULL) {
+        //XXX Is this right? Would this just cause a whole lot of busy looping while we wait for events?
+        LOGW("fgPlatformProcessSingleEvent: Missing current window. Skipping event processing");
+        return;
+    }
+
     int domain;
-    bps_event_t** eventPtr = &fgStructure.CurrentWindow->Window.pContext.event; //XXX Is there a more direct way to access the context?
-    bps_event_t* event;
     do
     {
-        if(*eventPtr != NULL) {
+        if(fgDisplay.pDisplay.event != NULL) {
             SFG_Window* window = fgStructure.CurrentWindow;
-            if (window != NULL && window->Window.Handle != NULL) {
+            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);
             }
 
-            event = *eventPtr;
-            domain = bps_event_get_domain(event);
+            domain = bps_event_get_domain(fgDisplay.pDisplay.event);
             if (domain == screen_get_domain()) {
                 int eventType;
-                screen_event_t screenEvent = screen_event_get_event(event);
+                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) {
 
@@ -283,7 +298,13 @@ void fgPlatformProcessSingleEvent ( void )
                 {
                     mtouch_event_t touchEvent;
                     screen_get_mtouch_event(screenEvent, &touchEvent, 0);
-                    LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_MTOUCH_*: Type: 0x%X, X: %d, Y: %d, Contact Id: %d", SLOG2_FA_SIGNED(eventType), SLOG2_FA_SIGNED(touchEvent.x), SLOG2_FA_SIGNED(touchEvent.y), SLOG2_FA_SIGNED(touchEvent.contact_id));
+                    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);
+
                     if(touchEvent.contact_id == 0) {
                         int size[2];
                         screen_get_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size);
@@ -301,6 +322,8 @@ void fgPlatformProcessSingleEvent ( void )
                         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;
                 }
 
@@ -318,13 +341,17 @@ void fgPlatformProcessSingleEvent ( void )
                     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", SLOG2_FA_SIGNED(buttons), SLOG2_FA_SIGNED(position[0]), SLOG2_FA_SIGNED(position[1]), SLOG2_FA_SIGNED(wheel));
+                    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) {
@@ -372,9 +399,49 @@ void fgPlatformProcessSingleEvent ( void )
                     }
 
                     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;
-                        //TODO: Implement wheel support (based on fg_main_mswin... though it seems excessive)
+                        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;
                 }
 
@@ -385,11 +452,19 @@ void fgPlatformProcessSingleEvent ( void )
                     int value;
                     screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);
                     screen_get_event_property_iv(screenEvent, SCREEN_PROPERTY_KEY_SYM, &value);
-                    LOGI("fgPlatformProcessSingleEvent: SCREEN_EVENT_KEYBOARD. Flags: 0x%X, Sym: 0x%X", SLOG2_FA_SIGNED(flags), SLOG2_FA_SIGNED(value));
-                    // Suppress key repeats if desired
-                    if ((flags & KEY_REPEAT) == 0 || (fgState.KeyRepeat == GLUT_KEY_REPEAT_ON && !fgStructure.CurrentWindow->State.IgnoreKeyRepeat)) {
+                    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));
@@ -402,7 +477,11 @@ void fgPlatformProcessSingleEvent ( void )
                             } 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;
                 }
@@ -416,13 +495,13 @@ void fgPlatformProcessSingleEvent ( void )
                     break;
                 }
             } else if (domain == navigator_get_domain()) {
-                int eventType = bps_event_get_code(event);
+                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(event);
+                    navigator_window_state_t state = navigator_event_get_window_state(fgDisplay.pDisplay.event);
                     switch (state)
                     {
                     case NAVIGATOR_WINDOW_FULLSCREEN:
@@ -444,6 +523,9 @@ void fgPlatformProcessSingleEvent ( void )
                 case NAVIGATOR_EXIT:
                 {
                     LOGI("fgPlatformProcessSingleEvent: NAVIGATOR_EXIT");
+
+                    fgPlatformMainLoopPostWork();
+
                     /* User closed the application for good, let's kill the window */
                     SFG_Window* window = fgStructure.CurrentWindow;
                     if (window != NULL) {
@@ -457,10 +539,14 @@ void fgPlatformProcessSingleEvent ( void )
                 case NAVIGATOR_SWIPE_DOWN:
                 case NAVIGATOR_BACK:
                 case NAVIGATOR_WINDOW_ACTIVE:
+                case NAVIGATOR_WINDOW_INACTIVE:
+                case NAVIGATOR_KEYBOARD_STATE:
+                case NAVIGATOR_KEYBOARD_POSITION:
                 case NAVIGATOR_DEVICE_LOCK_STATE:
                 case NAVIGATOR_WINDOW_COVER:
                 case NAVIGATOR_WINDOW_COVER_ENTER:
                 case NAVIGATOR_WINDOW_COVER_EXIT:
+                case NAVIGATOR_APP_STATE:
                     //XXX Should probably do something with these
                     break;
 
@@ -470,17 +556,32 @@ void fgPlatformProcessSingleEvent ( void )
                 }
             }
         }
-    } while(bps_get_event(eventPtr, 1) == BPS_SUCCESS && *eventPtr != NULL);
+    } while(bps_get_event(&fgDisplay.pDisplay.event, 1) == BPS_SUCCESS && fgDisplay.pDisplay.event != NULL);
 
     /* Reset event to reduce chances of triggering something */
-    *eventPtr = NULL;
+    fgDisplay.pDisplay.event = NULL;
 }
 
 void fgPlatformMainLoopPreliminaryWork ( void )
 {
     LOGI("fgPlatformMainLoopPreliminaryWork");
+
+    /* Request navigator events */
+    navigator_request_events(0);
+    //XXX rotation lock? navigator_rotation_lock(true);
+
+    /* Request window events */
+    screen_request_events(fgDisplay.pDisplay.screenContext);
 }
 
+void fgPlatformMainLoopPostWork ( void )
+{
+    LOGI("fgPlatformMainLoopPostWork");
+
+    screen_stop_events(fgDisplay.pDisplay.screenContext);
+
+    navigator_stop_events(0);
+}
 
 /* deal with work list items */
 void fgPlatformInitWork(SFG_Window* window)
@@ -538,4 +639,3 @@ void fgPlatformVisibilityWork(SFG_Window* window)
         break;
     }
 }
-