Exemplo n.º 1
0
//------------------------ Match keypress to item ------------------
int menu_match_keypress( MENU * menu, int keypress )
{
	int i;
	char c;
	char *letter;

	if ((keypress & KEY_CTRLED) || (keypress & KEY_SHIFTED))
		return -1;
	
	keypress &= 0xFF;

	c = key_ascii();
			
	for (i=0; i< menu->NumItems; i++ )
	{
		letter = strrchr( menu->Item[i].Text, '&' );
		if (letter)
		{
			letter++;
			if (c==tolower(*letter))
				return i;
		}
	}
	return -1;
}
Exemplo n.º 2
0
int MarkerInputMessage(int key)
{
	switch( key )
	{
		case KEY_F8:
		case KEY_ESC:
			DefiningMarkerMessage = 0;
			key_toggle_repeat(0);
			game_flush_inputs();
			break;
		case KEY_LEFT:
		case KEY_BACKSP:
		case KEY_PAD4:
			if (Marker_index > 0)
				Marker_index--;
			Marker_input[Marker_index] = 0;
			break;
		case KEY_ENTER:
			strcpy (MarkerMessage[(Player_num*2)+MarkerBeingDefined],Marker_input);
			DropMarker(MarkerBeingDefined);
			LastMarkerDropped = MarkerBeingDefined;
			key_toggle_repeat(0);
			game_flush_inputs();
			DefiningMarkerMessage = 0;
			break;
		default:
		{
			int ascii = key_ascii();
			if ((ascii < 255 ))
				if (Marker_index < 38 )
				{
					Marker_input[Marker_index++] = ascii;
					Marker_input[Marker_index] = 0;
				}
			return 0;
			break;
		}
	}
	
	return 1;
}
Exemplo n.º 3
0
static window_event_result con_handler(window *wind,const d_event &event, const unused_window_userdata_t *)
{
	int key;
	static fix64 last_scroll_time = 0;
	
	switch (event.type)
	{
		case EVENT_WINDOW_ACTIVATED:
			key_toggle_repeat(1);
			break;

		case EVENT_WINDOW_DEACTIVATED:
			key_toggle_repeat(0);
			con_size = 0;
			con_state = CON_STATE_CLOSED;
			break;

		case EVENT_KEY_COMMAND:
			key = event_key_get(event);
			switch (key)
			{
				case KEY_SHIFTED + KEY_ESC:
					switch (con_state)
					{
						case CON_STATE_OPEN:
						case CON_STATE_OPENING:
							con_state = CON_STATE_CLOSING;
							break;
						case CON_STATE_CLOSED:
						case CON_STATE_CLOSING:
							con_state = CON_STATE_OPENING;
						default:
							break;
					}
					break;
				case KEY_PAGEUP:
					con_scroll_offset+=CON_SCROLL_OFFSET;
					if (con_scroll_offset >= CON_LINES_MAX-1)
						con_scroll_offset = CON_LINES_MAX-1;
					while (con_buffer[CON_LINES_MAX-1-con_scroll_offset].line[0]=='\0')
						con_scroll_offset--;
					break;
				case KEY_PAGEDOWN:
					con_scroll_offset-=CON_SCROLL_OFFSET;
					if (con_scroll_offset<0)
						con_scroll_offset=0;
					break;
				case KEY_CTRLED + KEY_A:
				case KEY_HOME:              cli_cursor_home();      break;
				case KEY_END:
				case KEY_CTRLED + KEY_E:    cli_cursor_end();       break;
				case KEY_CTRLED + KEY_C:    cli_clear();            break;
				case KEY_LEFT:              cli_cursor_left();      break;
				case KEY_RIGHT:             cli_cursor_right();     break;
				case KEY_BACKSP:            cli_cursor_backspace(); break;
				case KEY_CTRLED + KEY_D:
				case KEY_DELETE:            cli_cursor_del();       break;
				case KEY_UP:                cli_history_prev();     break;
				case KEY_DOWN:              cli_history_next();     break;
				case KEY_TAB:               cli_autocomplete();     break;
				case KEY_ENTER:             cli_execute();          break;
				case KEY_INSERT:
					cli_toggle_overwrite_mode();
					break;
				default:
					int character = key_ascii();
					if (character == 255)
						break;
					cli_add_character(character);
					break;
			}
			return window_event_result::handled;

		case EVENT_WINDOW_DRAW:
			timer_delay2(50);
			if (con_state == CON_STATE_OPENING)
			{
				if (con_size < CON_LINES_ONSCREEN && timer_query() >= last_scroll_time+(F1_0/30))
				{
					last_scroll_time = timer_query();
					if (++ con_size >= CON_LINES_ONSCREEN)
						con_state = CON_STATE_OPEN;
				}
			}
			else if (con_state == CON_STATE_CLOSING)
			{
				if (con_size > 0 && timer_query() >= last_scroll_time+(F1_0/30))
				{
					last_scroll_time = timer_query();
					if (! -- con_size)
						con_state = CON_STATE_CLOSED;
				}
			}
			con_draw();
			if (con_state == CON_STATE_CLOSED && wind)
			{
				return window_event_result::close;
			}
			break;
		case EVENT_WINDOW_CLOSE:
			break;
		default:
			break;
	}
	
	return window_event_result::ignored;
}
Exemplo n.º 4
0
/**
 * Process the next input event.
 */
int32_t handle_input(struct android_app* app, AInputEvent* event) {
  SFG_Window* window = fgStructure.CurrentWindow;

  /* FIXME: in Android, when key is repeated, down and up events
     happen most often at the exact same time.  This makes it
     impossible to animate based on key press time. */
  /* e.g. down/up/wait/down/up rather than down/wait/down/wait/up */
  
  if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
    /* LOGI("action: %d", AKeyEvent_getAction(event)); */
    /* LOGI("keycode: %d", code); */
    int32_t code = AKeyEvent_getKeyCode(event);

    if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) {
      int32_t keypress = 0;
      unsigned char ascii = 0;
      if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) {
	INVOKE_WCB(*window, Special, (keypress, window->State.MouseX, window->State.MouseY));
	return EVENT_HANDLED;
      } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) {
	INVOKE_WCB(*window, Keyboard, (ascii, window->State.MouseX, window->State.MouseY));
	return EVENT_HANDLED;
      }
    }
    else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) {
      int32_t keypress = 0;
      unsigned char ascii = 0;
      if ((keypress = key_a2fg[code]) && FETCH_WCB(*window, Special)) {
	INVOKE_WCB(*window, SpecialUp, (keypress, window->State.MouseX, window->State.MouseY));
	return EVENT_HANDLED;
      } else if ((ascii = key_ascii(app, event)) && FETCH_WCB(*window, Keyboard)) {
	INVOKE_WCB(*window, KeyboardUp, (ascii, window->State.MouseX, window->State.MouseY));
	return EVENT_HANDLED;
      }
    }
  }

  if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
    int32_t action = AMotionEvent_getAction(event);
    float x = AMotionEvent_getX(event, 0);
    float y = AMotionEvent_getY(event, 0);
    LOGI("motion %.01f,%.01f action=%d", x, y, AMotionEvent_getAction(event));
    
    /* Virtual arrows PAD */
    // Don't interfere with existing mouse move event
    if (!touchscreen.in_mmotion) {
      struct vpad_state prev_vpad = touchscreen.vpad;
      touchscreen.vpad.left = touchscreen.vpad.right
	= touchscreen.vpad.up = touchscreen.vpad.down = false;

      int32_t width = ANativeWindow_getWidth(window->Window.Handle);
      int32_t height = ANativeWindow_getHeight(window->Window.Handle);
      if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_MOVE) {
	if ((x > 0 && x < 100) && (y > (height - 100) && y < height))
	  touchscreen.vpad.left = true;
	if ((x > 200 && x < 300) && (y > (height - 100) && y < height))
	  touchscreen.vpad.right = true;
	if ((x > 100 && x < 200) && (y > (height - 100) && y < height))
	  touchscreen.vpad.down = true;
	if ((x > 100 && x < 200) && (y > (height - 200) && y < (height - 100)))
	  touchscreen.vpad.up = true;
      }
      if (action == AMOTION_EVENT_ACTION_DOWN && 
	  (touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up))
	touchscreen.vpad.on = true;
      if (action == AMOTION_EVENT_ACTION_UP)
	touchscreen.vpad.on = false;
      if (prev_vpad.left != touchscreen.vpad.left
	  || prev_vpad.right != touchscreen.vpad.right
	  || prev_vpad.up != touchscreen.vpad.up
	  || prev_vpad.down != touchscreen.vpad.down
	  || prev_vpad.on != touchscreen.vpad.on) {
	if (FETCH_WCB(*window, Special)) {
	  if (prev_vpad.left == false && touchscreen.vpad.left == true)
	    INVOKE_WCB(*window, Special, (GLUT_KEY_LEFT, x, y));
	  else if (prev_vpad.right == false && touchscreen.vpad.right == true)
	    INVOKE_WCB(*window, Special, (GLUT_KEY_RIGHT, x, y));
	  else if (prev_vpad.up == false && touchscreen.vpad.up == true)
	    INVOKE_WCB(*window, Special, (GLUT_KEY_UP, x, y));
	  else if (prev_vpad.down == false && touchscreen.vpad.down == true)
	    INVOKE_WCB(*window, Special, (GLUT_KEY_DOWN, x, y));
	}
	if (FETCH_WCB(*window, SpecialUp)) {
	  if (prev_vpad.left == true && touchscreen.vpad.left == false)
	    INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_LEFT, x, y));
	  if (prev_vpad.right == true && touchscreen.vpad.right == false)
	    INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_RIGHT, x, y));
	  if (prev_vpad.up == true && touchscreen.vpad.up == false)
	    INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_UP, x, y));
	  if (prev_vpad.down == true && touchscreen.vpad.down == false)
	    INVOKE_WCB(*window, SpecialUp, (GLUT_KEY_DOWN, x, y));
	}
	return EVENT_HANDLED;
      }
    }
    
    /* Normal mouse events */
    if (!touchscreen.vpad.on) {
      window->State.MouseX = x;
      window->State.MouseY = y;
      LOGI("Changed mouse position: %d,%d", x, y);
      if (action == AMOTION_EVENT_ACTION_DOWN && FETCH_WCB(*window, Mouse)) {
	touchscreen.in_mmotion = true;
	INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_DOWN, x, y));
      } else if (action == AMOTION_EVENT_ACTION_UP && FETCH_WCB(*window, Mouse)) {
	touchscreen.in_mmotion = false;
	INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, GLUT_UP, x, y));
      } else if (action == AMOTION_EVENT_ACTION_MOVE && FETCH_WCB(*window, Motion)) {
	INVOKE_WCB(*window, Motion, (x, y));
      }
    }
    
    return EVENT_HANDLED;
  }

  /* Let Android handle other events (e.g. Back and Menu buttons) */
  return EVENT_NOT_HANDLED;
}
Exemplo n.º 5
0
int FinalCheats(int key)
{
	static char cheat_buffer[CHEAT_MAX_LEN] = "AAAAAAAAAAAAAAA";
	int i = 0, gotcha = 0;

	if (Game_mode & GM_MULTI)
		return 0;

	for (i = 1; i < CHEAT_MAX_LEN; i++)
		cheat_buffer[i-1] = cheat_buffer[i];
	cheat_buffer[CHEAT_MAX_LEN-1] = key_ascii();
	for (i = 0; i < NUM_CHEATS; i++)
	{
		int cheatlen = strlen(cheat_codes[i].string);
		Assert(cheatlen <= CHEAT_MAX_LEN);
		if (d_strnicmp(cheat_codes[i].string, cheat_buffer+CHEAT_MAX_LEN-cheatlen, cheatlen)==0)
		{
			if (!cheats.enabled && *cheat_codes[i].stateptr != cheats.enabled)
				break;
			if (!cheats.enabled)
				HUD_init_message(HM_DEFAULT, TXT_CHEATS_ENABLED);
			*cheat_codes[i].stateptr = !*cheat_codes[i].stateptr;
			cheats.enabled = 1;
			digi_play_sample( SOUND_CHEATER, F1_0);
			Players[Player_num].score = 0;
			gotcha = i;
			break;
		}
	}
	
	if (!gotcha)
		return 0;

	if (cheat_codes[gotcha].stateptr == &cheats.wowie)
	{
		HUD_init_message_literal(HM_DEFAULT, TXT_WOWIE_ZOWIE);

		Players[Player_num].primary_weapon_flags |= 0xff ^ (HAS_PLASMA_FLAG | HAS_FUSION_FLAG);
		Players[Player_num].secondary_weapon_flags |= 0xff ^ (HAS_SMART_FLAG | HAS_MEGA_FLAG);

		for (i=0; i<3; i++)
			Players[Player_num].primary_ammo[i] = Primary_ammo_max[i];
		for (i=0; i<3; i++)
			Players[Player_num].secondary_ammo[i] = Secondary_ammo_max[i];

		if (Newdemo_state == ND_STATE_RECORDING)
			newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);

		Players[Player_num].energy = MAX_ENERGY;
		Players[Player_num].laser_level = MAX_LASER_LEVEL;
		Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
		update_laser_weapon_info();
	}

	if (cheat_codes[gotcha].stateptr == &cheats.wowie2)
	{
		HUD_init_message(HM_DEFAULT, "SUPER %s",TXT_WOWIE_ZOWIE);

		Players[Player_num].primary_weapon_flags = 0xff;
		Players[Player_num].secondary_weapon_flags = 0xff;

		for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
			Players[Player_num].primary_ammo[i] = Primary_ammo_max[i];
		for (i=0; i<MAX_SECONDARY_WEAPONS; i++)
			Players[Player_num].secondary_ammo[i] = Secondary_ammo_max[i];

		if (Newdemo_state == ND_STATE_RECORDING)
			newdemo_record_laser_level(Players[Player_num].laser_level, MAX_LASER_LEVEL);

		Players[Player_num].energy = MAX_ENERGY;
		Players[Player_num].laser_level = MAX_LASER_LEVEL;
		Players[Player_num].flags |= PLAYER_FLAGS_QUAD_LASERS;
		update_laser_weapon_info();
	}

	if (cheat_codes[gotcha].stateptr == &cheats.allkeys)
	{
		HUD_init_message_literal(HM_DEFAULT, TXT_ALL_KEYS);
		Players[Player_num].flags |= PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY;
	}

	if (cheat_codes[gotcha].stateptr == &cheats.invul)
	{
		Players[Player_num].flags ^= PLAYER_FLAGS_INVULNERABLE;
		HUD_init_message(HM_DEFAULT, "%s %s!", TXT_INVULNERABILITY, (Players[Player_num].flags&PLAYER_FLAGS_INVULNERABLE)?TXT_ON:TXT_OFF);
		Players[Player_num].invulnerable_time = GameTime64+i2f(1000);
	}

	if (cheat_codes[gotcha].stateptr == &cheats.cloak)
	{
		Players[Player_num].flags ^= PLAYER_FLAGS_CLOAKED;
		HUD_init_message(HM_DEFAULT, "%s %s!", TXT_CLOAK, (Players[Player_num].flags&PLAYER_FLAGS_CLOAKED)?TXT_ON:TXT_OFF);
		if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)
		{
			ai_do_cloak_stuff();
			Players[Player_num].cloak_time = GameTime64;
		}
	}

	if (cheat_codes[gotcha].stateptr == &cheats.shields)
	{
		HUD_init_message_literal(HM_DEFAULT, TXT_FULL_SHIELDS);
		Players[Player_num].shields = MAX_SHIELDS;
	}

	if (cheat_codes[gotcha].stateptr == &cheats.extralife)
	{
		if (Players[Player_num].lives<50)
		{
			Players[Player_num].lives++;
			HUD_init_message_literal(HM_DEFAULT, "Extra life!");
		}
	}

	if (cheat_codes[gotcha].stateptr == &cheats.killreactor)
	{
		kill_and_so_forth();
	}

	if (cheat_codes[gotcha].stateptr == &cheats.exitpath)
	{
#ifdef SHOW_EXIT_PATH
		if (create_special_path())
			HUD_init_message_literal(HM_DEFAULT, "Exit path illuminated!");
#endif
	}

	if (cheat_codes[gotcha].stateptr == &cheats.levelwarp)
	{
		newmenu_item m;
		char text[10]="";
		int new_level_num;
		int item;
		*cheat_codes[gotcha].stateptr = 0;
		m.type=NM_TYPE_INPUT; m.text_len = 10; m.text = text;
		item = newmenu_do( NULL, TXT_WARP_TO_LEVEL, 1, &m, NULL, NULL );
		if (item != -1) {
			new_level_num = atoi(m.text);
			if (new_level_num!=0 && new_level_num>=0 && new_level_num<=Last_level)
			{
				window_set_visible(Game_wind, 0);
				StartNewLevel(new_level_num);
				window_set_visible(Game_wind, 1);
			}
		}
	}

	if (cheat_codes[gotcha].stateptr == &cheats.ghostphysics)
	{
		HUD_init_message(HM_DEFAULT, "%s %s!", "Ghosty mode", cheats.ghostphysics?TXT_ON:TXT_OFF);
	}

	if (cheat_codes[gotcha].stateptr == &cheats.rapidfire)
	{
		do_megawow_powerup(200);
	}

	if (cheat_codes[gotcha].stateptr == &cheats.turbo)
	{
		HUD_init_message(HM_DEFAULT, "%s %s!", "Turbo mode", cheats.turbo?TXT_ON:TXT_OFF);
	}

	if (cheat_codes[gotcha].stateptr == &cheats.robotfiringsuspended)
	{
		HUD_init_message(HM_DEFAULT, "Robot firing %s!", cheats.robotfiringsuspended?TXT_OFF:TXT_ON);
	}

	if (cheat_codes[gotcha].stateptr == &cheats.acid)
	{
		HUD_init_message_literal(HM_DEFAULT, cheats.acid?"Going up!":"Coming down!");
	}

	return 1;
}
Exemplo n.º 6
0
int ui_inputbox_do( UI_DIALOG *dlg, UI_GADGET_INPUTBOX * inputbox, d_event *event )
{
	unsigned char ascii;
	int keypress = 0;
	int rval = 0;
	
	if (event->type == EVENT_KEY_COMMAND)
		keypress = event_key_get(event);

	inputbox->oldposition = inputbox->position;
	inputbox->pressed=0;

	if (dlg->keyboard_focus_gadget==(UI_GADGET *)inputbox)
	{
		switch( keypress )
		{
		case 0:
			break;
		case (KEY_LEFT):
		case (KEY_BACKSP):
			if (inputbox->position > 0)
				inputbox->position--;
			inputbox->text[inputbox->position] = 0;
			inputbox->status = 1;
			if (inputbox->first_time) inputbox->first_time = 0;
			rval = 1;
			break;
		case (KEY_ENTER):
			inputbox->pressed=1;
			inputbox->status = 1;
			if (inputbox->first_time) inputbox->first_time = 0;
			rval = 1;
			break;
		default:
			ascii = key_ascii();
			if ((ascii < 255 ) && (inputbox->position < inputbox->length-2))
			{
				if (inputbox->first_time) {
					inputbox->first_time = 0;
					inputbox->position = 0;
				}
				inputbox->text[inputbox->position++] = ascii;
				inputbox->text[inputbox->position] = 0;
				rval = 1;
			}
			inputbox->status = 1;
			break;
		}
	} else {
		inputbox->first_time = 1;
	}
	
	if (inputbox->pressed)
	{
		ui_gadget_send_event(dlg, EVENT_UI_GADGET_PRESSED, (UI_GADGET *)inputbox);
		rval = 1;
	}
		
	if (event->type == EVENT_WINDOW_DRAW)
		ui_draw_inputbox( dlg, inputbox );

	return rval;
}
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;
    }

    if(fgDisplay.pDisplay.event == NULL)
        /* Nothing to do */
        return;

    int domain;
    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;
            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);
#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));

                /* 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);
                    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);
#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 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);

                // 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 */
                    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;
            }

            case SCREEN_EVENT_PROPERTY:
            case SCREEN_EVENT_IDLE:
                break;

            default:
                LOGW("fgPlatformProcessSingleEvent: unknown screen event: 0x%X", SLOG2_FA_SIGNED(eventType));
                break;
            }
        } else if (domain == navigator_get_domain()) {
            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);
                if(window->State.pWState.windowCovered == GL_FALSE)
                {
                    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;
            }

            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) {
                    fgDestroyWindow(window);
                } 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;
            }

            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;

#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;

            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 */
                window->State.pWState.newWidth = 0;
                window->State.pWState.newHeight = 0;

                /* Done rotating */
                navigator_done_orientation(fgDisplay.pDisplay.event);
                break;

            case NAVIGATOR_BACK:
                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:
                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;

#ifndef __PLAYBOOK__
            case NAVIGATOR_KEYBOARD_STATE:
            {
                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:
            {
                /* 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;

            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 like it doesn't 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;
#endif

            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;
            }
        }
#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 */
    fgDisplay.pDisplay.event = NULL;
}