Merge pull request #8 from rcmaniac25/blackberry

Added BlackBerry support
This commit is contained in:
Diederick C. Niehorster 2014-01-24 02:22:53 -08:00
commit 390a7ec398
14 changed files with 2029 additions and 38 deletions

View File

@ -39,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 :)

View File

@ -118,25 +118,42 @@ IF(WIN32)
)
ENDIF()
ELSEIF(ANDROID)
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/native_app_glue/android_native_app_glue.c
src/android/native_app_glue/android_native_app_glue.h
src/android/fg_internal_android.h
src/android/fg_cursor_android.c
src/android/fg_ext_android.c
src/android/fg_gamemode_android.c
src/android/fg_init_android.c
src/android/fg_input_devices_android.c
src/android/fg_joystick_android.c
src/android/fg_main_android.c
src/android/fg_main_android.h
src/android/fg_runtime_android.c
src/android/fg_spaceball_android.c
src/android/fg_state_android.c
src/android/fg_structure_android.c
src/android/fg_window_android.c
)
IF(ANDROID)
LIST(APPEND FREEGLUT_SRCS
src/android/native_app_glue/android_native_app_glue.c
src/android/native_app_glue/android_native_app_glue.h
src/android/fg_internal_android.h
src/android/fg_init_android.c
src/android/fg_input_devices_android.c
src/android/fg_main_android.c
src/android/fg_main_android.h
src/android/fg_runtime_android.c
src/android/fg_state_android.c
src/android/fg_structure_android.c
src/android/fg_window_android.c
)
ELSE()
LIST(APPEND FREEGLUT_SRCS
src/blackberry/fg_internal_blackberry.h
src/blackberry/fg_init_blackberry.c
src/x11/fg_input_devices_x11.c
src/blackberry/fg_main_blackberry.c
src/blackberry/fg_state_blackberry.c
src/blackberry/fg_structure_blackberry.c
src/blackberry/fg_window_blackberry.c
)
ENDIF()
ELSE()
LIST(APPEND FREEGLUT_SRCS
src/x11/fg_cursor_x11.c
@ -219,14 +236,14 @@ ENDIF()
IF(CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
IF(!ANDROID)
IF(NOT(ANDROID OR BLACKBERRY))
# not setting -ansi as EGL/KHR headers doesn't support it
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
ENDIF()
ENDIF(CMAKE_COMPILER_IS_GNUCC)
INCLUDE(CheckIncludeFiles)
IF(UNIX AND NOT ANDROID)
IF(UNIX AND NOT(ANDROID OR BLACKBERRY))
FIND_PACKAGE(X11 REQUIRED)
LIST(APPEND LIBS ${X11_LIBRARIES})
IF(X11_Xrandr_FOUND)
@ -251,6 +268,17 @@ IF(ANDROID)
# -landroid for ANativeWindow
# -llog for native Android logging
LIST(APPEND LIBS android log)
ELSEIF(BLACKBERRY)
if(PLAYBOOK)
# -lbps for event loop
# -screen for native screen
LIST(APPEND LIBS bps screen)
ELSE()
# -lbps for event loop
# -lslog2 for logging
# -screen for native screen
LIST(APPEND LIBS bps slog2 screen)
ENDIF()
ENDIF()
INCLUDE(CheckFunctionExists)
@ -464,12 +492,24 @@ IF(WIN32)
ELSEIF(FREEGLUT_GLES2)
IF(ANDROID)
SET(PC_LIBS_PRIVATE "-llog -landroid -lGLESv2 -lEGL -lm")
ELSEIF(BLACKBERRY)
IF(PLAYBOOK)
SET(PC_LIBS_PRIVATE "-lbps -lscreen -lGLESv2 -lEGL -lm")
ELSE()
SET(PC_LIBS_PRIVATE "-lbps -lslog2 -lscreen -lGLESv2 -lEGL -lm")
ENDIF()
ELSE()
SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGLESv2 -lEGL -lm")
ENDIF()
ELSEIF(FREEGLUT_GLES1)
IF(ANDROID)
SET(PC_LIBS_PRIVATE "-llog -landroid -lGLESv1_CM -lEGL -lm")
ELSEIF(BLACKBERRY)
IF(PLAYBOOK)
SET(PC_LIBS_PRIVATE "-lbps -lscreen -lGLESv1_CM -lEGL -lm")
ELSE()
SET(PC_LIBS_PRIVATE "-lbps -lslog2 -lscreen -lGLESv1_CM -lEGL -lm")
ENDIF()
ELSE()
SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGLESv1_CM -lEGL -lm")
ENDIF()

View File

@ -0,0 +1,21 @@
# ------------------------------------------------------------------------------
# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK
# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended).
#
# Usage Linux:
# $ source /absolute/path/to/the/bbndk/bbndk-env.sh
# $ mkdir build
# $ cd build
# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES2=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
# $ make -j8
#
# Usage Mac:
# Same as the steps on Linux
#
# Usage Windows:
# > /absolute/path/to/the/bbndk/bbndk-env.bat
# > mkdir build
# > cd build
# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES2=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
# > make -j8
#

View File

@ -0,0 +1,215 @@
# ------------------------------------------------------------------------------
# BlackBerry CMake toolchain file, for use with the BlackBerry 10 NDK
# Requires cmake 2.6.3 or newer (2.8.3 or newer is recommended).
#
# Usage Linux:
# $ source /absolute/path/to/the/bbndk/bbndk-env.sh
# $ mkdir build
# $ cd build
# $ cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES2=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
# $ make -j8
#
# Usage Mac:
# Same as the steps on Linux
#
# Usage Windows:
# > /absolute/path/to/the/bbndk/bbndk-env.bat
# > mkdir build
# > cd build
# > cmake .. -DCMAKE_TOOLCHAIN_FILE="../blackberry.toolchain.cmake" -DBLACKBERRY_ARCHITECTURE=arm -DFREEGLUT_GLES2=ON -DFREEGLUT_BUILD_DEMOS=NO -DCMAKE_VERBOSE_MAKEFILE=TRUE -G "Eclipse CDT4 - Unix Makefiles"
# > make -j8
#
cmake_minimum_required( VERSION 2.6.3 )
if( DEFINED CMAKE_CROSSCOMPILING )
# Subsequent toolchain loading is not really needed
return()
endif()
set( BLACKBERRY_TOOLCHAIN_ROOT "$ENV{QNX_HOST}" )
set( BLACKBERRY_TARGET_ROOT "$ENV{QNX_TARGET}" )
set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_SYSTEM_VERSION 1 )
# Check for PlayBook
if( EXISTS "${BLACKBERRY_TARGET_ROOT}/x86/lib/gcc/4.4.2" )
set( PLAYBOOK True )
endif()
# STL version: by default gnustl_static will be used
set( BLACKBERRY_USE_STLPORT FALSE CACHE BOOL "Experimental: use stlport_static instead of gnustl_static")
mark_as_advanced( BLACKBERRY_USE_STLPORT )
# Detect host platform
set( TOOL_OS_SUFFIX "" )
if( CMAKE_HOST_APPLE )
set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "darwin-x86" )
elseif( CMAKE_HOST_WIN32 )
set( BLACKBERRY_NDK_HOST_SYSTEM_NAME "windows" )
set( TOOL_OS_SUFFIX ".exe" )
elseif( CMAKE_HOST_UNIX )
set(BLACKBERRY_NDK_HOST_SYSTEM_NAME "linux-x86" )
else()
message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
endif()
# Specify the cross compiler
set( CMAKE_C_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" )
set( CMAKE_CXX_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "g++" )
set( CMAKE_ASM_COMPILER "$ENV{QNX_HOST}/usr/bin/qcc${TOOL_OS_SUFFIX}" CACHE PATH "Assembler" )
if( CMAKE_VERSION VERSION_LESS 2.8.5 )
set( CMAKE_ASM_COMPILER_ARG1 "-c" )
endif()
# There may be a way to make cmake reduce these TODO
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
set( NEUTRINO_ARCH "v7" )
else()
set( NEUTRINO_ARCH "" )
endif()
set( CMAKE_STRIP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
set( CMAKE_AR "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
set( CMAKE_LINKER "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
set( CMAKE_NM "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
set( CMAKE_OBJCOPY "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
set( CMAKE_OBJDUMP "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}${NEUTRINO_ARCH}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
set( CMAKE_RANLIB "$ENV{QNX_HOST}/usr/bin/nto${BLACKBERRY_ARCHITECTURE}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" )
# Installer
#if( APPLE )
# find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
# if( NOT CMAKE_INSTALL_NAME_TOOL )
# message( FATAL_ERROR "Could not find install_name_tool, please check your #installation." )
# endif()
# mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
# endif()
# Setup output directories
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
set( CMAKE_INSTALL_PREFIX "${BLACKBERRY_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
else()
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
endif()
# Includes
if( PLAYBOOK )
list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/usr/include" )
else()
list( APPEND BLACKBERRY_SYSTEM_INCLUDE_DIRS "${BLACKBERRY_TARGET_ROOT}/qnx6/usr/include" )
endif()
# Flags and preprocessor definitions
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
if( PLAYBOOK )
set( BLACKBERRY_CC_FLAGS " -V4.4.2,gcc_ntoarmv7le -D__PLAYBOOK__" )
set( BLACKBERRY_CXX_FLAGS " -V4.4.2,gcc_ntoarmv7le -Y_gpp -D__PLAYBOOK__" )
else()
set( BLACKBERRY_CC_FLAGS " -V4.6.3,gcc_ntoarmv7le -D__QNX__" )
set( BLACKBERRY_CXX_FLAGS " -V4.6.3,gcc_ntoarmv7le -Y_gpp -D__QNX__" )
endif()
else()
if( PLAYBOOK )
set( BLACKBERRY_CC_FLAGS " -V4.4.2,gcc_ntox86 -D__PLAYBOOK__" )
set( BLACKBERRY_CXX_FLAGS " -V4.4.2,gcc_ntox86 -Y_gpp -D__PLAYBOOK__" )
else()
set( BLACKBERRY_CC_FLAGS " -V4.6.3,gcc_ntox86 -D__QNX__" )
set( BLACKBERRY_CXX_FLAGS " -V4.6.3,gcc_ntox86 -Y_gpp -D__QNX__" )
endif()
endif()
set( BLACKBERRY 1 )
# NDK flags
set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" )
set( CMAKE_C_FLAGS "${BLACKBERRY_CC_FLAGS}" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexceptions" )
# Release and Debug flags
if( BLACKBERRY_ARCHITECTURE STREQUAL "arm" )
set( CMAKE_CXX_FLAGS_RELEASE "-mthumb -O3" )
set( CMAKE_C_FLAGS_RELEASE "-mthumb -O3" )
set( CMAKE_CXX_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
set( CMAKE_C_FLAGS_DEBUG "-marm -Os -finline-limit=64" )
else()
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i486" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i486" )
endif()
# Cache flags
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags" )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "c++ Release flags" )
set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}" CACHE STRING "c Release flags" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "c++ Debug flags" )
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" CACHE STRING "c Debug flags" )
set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "linker flags" )
SET( CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "" CACHE STRING "linker flags")
SET( CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "" CACHE STRING "linker flags")
set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "linker flags" )
set( CMAKE_EXE_LINKER_FLAGS "-lstdc++" CACHE STRING "linker flags" )
# Finish flags
set( BLACKBERRY_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS}" CACHE INTERNAL "Extra BlackBerry compiler flags")
set( BLACKBERRY_LINKER_FLAGS "${BLACKBERRY_LINKER_FLAGS}" CACHE INTERNAL "Extra BlackBerry linker flags")
set( CMAKE_CXX_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
set( CMAKE_C_FLAGS "${BLACKBERRY_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
# Global flags for cmake client scripts to change behavior
set( BLACKBERRY True )
# Find the Target environment
set( CMAKE_FIND_ROOT_PATH "${CMAKE_SOURCE_DIR}" "${BLACKBERRY_TARGET_ROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
# Search for libraries and includes in the ndk toolchain
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
# Macro to find packages on the host OS
macro( find_host_package )
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
if( CMAKE_HOST_WIN32 )
SET( WIN32 1 )
SET( UNIX )
elseif( CMAKE_HOST_APPLE )
SET( APPLE 1 )
SET( UNIX )
endif()
find_package( ${ARGN} )
SET( WIN32 )
SET( APPLE )
SET( UNIX 1 )
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
endmacro()
# Macro to find programs on the host OS
macro( find_host_program )
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
if( CMAKE_HOST_WIN32 )
SET( WIN32 1 )
SET( UNIX )
elseif( CMAKE_HOST_APPLE )
SET( APPLE 1 )
SET( UNIX )
endif()
find_program( ${ARGN} )
SET( WIN32 )
SET( APPLE )
SET( UNIX 1 )
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
endmacro()
# We are doing cross compiling, reset the OS information of the Building system
UNSET( APPLE )
UNSET( WIN32 )
UNSET( UNIX )

View File

@ -0,0 +1,107 @@
/*
* fg_init_blackberry.c
*
* Various freeglut initialization functions.
*
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "fg_internal.h"
#include "fg_init.h"
#include "egl/fg_init_egl.h"
#include <bps/bps.h>
#include <screen/screen.h>
void fgPlatformInitialize()
{
bps_initialize();
fghPlatformInitializeEGL();
/* Prepare for screen events */
fgDisplay.pDisplay.event = NULL;
fgDisplay.pDisplay.screenContext = NULL;
/* Create window */
if (screen_create_context(&fgDisplay.pDisplay.screenContext, 0)) {
fgError("Could not create screen context");
return;
}
/* Get screen size */
int displayCount;
screen_display_t* displays;
int vals[2];
if(screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount)) {
fgWarning("Could not get display count. Screen size not determined and will be left at default values");
} else if(displayCount >= 1) {
displays = (screen_display_t*)calloc(displayCount, sizeof(screen_display_t));
if(screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DISPLAYS, (void**)displays)) {
fgWarning("Could not get displays. Screen size not determined and will be left at default values");
} else {
/* We only care about the first one, which is the device display */
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_SIZE, vals)) {
fgWarning("Could not get display size. Values will be left at default");
} else {
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_ROTATION, &displayCount) || (displayCount == 0 || displayCount == 180)) {
fgDisplay.ScreenWidth = vals[0];
fgDisplay.ScreenHeight = vals[1];
} else {
fgDisplay.ScreenWidth = vals[1];
fgDisplay.ScreenHeight = vals[0];
}
}
if(screen_get_display_property_iv(displays[0], SCREEN_PROPERTY_PHYSICAL_SIZE, vals)) {
fgWarning("Could not get physical display size. Values will be left at default");
} else {
fgDisplay.ScreenWidthMM = vals[0];
fgDisplay.ScreenHeightMM = vals[1];
}
}
free(displays);
}
/* Get start time */
fgState.Time = fgSystemTime();
fgState.Initialised = GL_TRUE;
}
void fgPlatformCloseDisplay()
{
fghPlatformCloseDisplayEGL();
screen_destroy_context(fgDisplay.pDisplay.screenContext);
fgDisplay.pDisplay.screenContext = NULL;
bps_shutdown();
}
/**
* Close joystick and serial input devices
*/
void fgPlatformDeinitialiseInputDevices ( void )
{
fghCloseInputDevices ();
fgState.JoysticksInitialised = GL_FALSE;
fgState.InputDevsInitialised = GL_FALSE;
}

View File

@ -0,0 +1,136 @@
/*
* fg_internal_blackberry.h
*
* The freeglut library private include file.
*
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FREEGLUT_INTERNAL_BLACKBERRY_H
#define FREEGLUT_INTERNAL_BLACKBERRY_H
//Minor modified version of fg_internal_android.h
/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
/* BlackBerry OpenGL ES is accessed through EGL */
#include "egl/fg_internal_egl.h"
#include <screen/screen.h>
#include <bps/event.h>
#include <bps/navigator.h>
/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
/* The structure used by display initialization in freeglut_init.c */
typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
struct tagSFG_PlatformDisplay
{
struct tagSFG_PlatformDisplayEGL egl;
screen_context_t screenContext;
bps_event_t* event;
EGLNativeWindowType single_native_window;
};
typedef struct tagSFG_PlatformContext SFG_PlatformContext;
/* SFG_PlatformContext is used for SFG_Window.Window */
struct tagSFG_PlatformContext
{
struct tagSFG_PlatformContextEGL egl;
};
/**
* Virtual PAD (spots on touchscreen that simulate keys)
*/
struct vpad_state {
bool on;
bool left;
bool right;
bool up;
bool down;
};
struct touchscreen {
struct vpad_state vpad;
bool in_mmotion;
};
/* -- INPUT DEFINITIONS ---------------------------------------------------- */
#define WHEEL_DELTA 120 //This is taken from http://msdn.microsoft.com/en-us/library/windows/desktop/ms646254(v=vs.85).aspx
/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */
/*
* Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c"
* interspersed
*/
/*
* We'll put these values in and that should
* allow the code to at least compile when there is
* no support. The JS open routine should error out
* and shut off all the code downstream anyway and if
* the application doesn't use a joystick we'll be fine.
*/
struct JS_DATA_TYPE
{
int buttons;
int x;
int y;
};
#define JS_RETURN (sizeof(struct JS_DATA_TYPE))
/* XXX It might be better to poll the operating system for the numbers of buttons and
* XXX axes and then dynamically allocate the arrays.
*/
#define _JS_MAX_AXES 16
typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
struct tagSFG_PlatformJoystick
{
struct JS_DATA_TYPE js;
char fname [ 128 ];
int fd;
};
/* Window's state description. This structure should be kept portable. */
typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
struct tagSFG_PlatformWindowState
{
int newWidth;
int newHeight;
int originalRotation;
navigator_window_state_t windowState;
GLboolean windowCovered;
#ifdef __PLAYBOOK__
int keyboardHeight;
GLboolean keyboardOpen;
#endif
};
/* Menu font and color definitions */
#define FREEGLUT_MENU_FONT NULL
#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f}
#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
#endif /* FREEGLUT_INTERNAL_BLACKBERRY_H */

View File

@ -0,0 +1,916 @@
/*
* fg_main_blackberry.c
*
* The BlackBerry-specific windows message processing methods.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "fg_internal.h"
#include "egl/fg_window_egl.h"
#ifdef NDEBUG
#define LOGI(...)
#endif
#ifdef __PLAYBOOK__
#include <sys/slog.h>
#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 <slog2.h>
#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 <sys/keycodes.h>
#include <input/screen_helpers.h>
#include <bps/bps.h>
#include <bps/event.h>
#include <bps/screen.h>
#include <bps/navigator.h>
#include <bps/virtualkeyboard.h>
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
extern void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify);
extern void fgPlatformFullScreenToggle( SFG_Window *win );
extern void fgPlatformPositionWindow( SFG_Window *window, int x, int y );
extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height );
extern void fgPlatformPushWindow( SFG_Window *window );
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 );
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) {
case KEYCODE_F1:
return GLUT_KEY_F1;
case KEYCODE_F2:
return GLUT_KEY_F2;
case KEYCODE_F3:
return GLUT_KEY_F3;
case KEYCODE_F4:
return GLUT_KEY_F4;
case KEYCODE_F5:
return GLUT_KEY_F5;
case KEYCODE_F6:
return GLUT_KEY_F6;
case KEYCODE_F7:
return GLUT_KEY_F7;
case KEYCODE_F8:
return GLUT_KEY_F8;
case KEYCODE_F9:
return GLUT_KEY_F9;
case KEYCODE_F10:
return GLUT_KEY_F10;
case KEYCODE_F11:
return GLUT_KEY_F11;
case KEYCODE_F12:
return GLUT_KEY_F12;
case KEYCODE_PG_UP:
return GLUT_KEY_PAGE_UP;
case KEYCODE_PG_DOWN:
return GLUT_KEY_PAGE_DOWN;
case KEYCODE_HOME:
return GLUT_KEY_HOME;
case KEYCODE_END:
return GLUT_KEY_END;
case KEYCODE_INSERT:
return GLUT_KEY_INSERT;
case KEYCODE_UP:
//case KEYCODE_KP_UP:
return GLUT_KEY_UP;
case KEYCODE_DOWN:
//case KEYCODE_KP_DOWN:
return GLUT_KEY_DOWN;
case KEYCODE_LEFT:
//case KEYCODE_KP_LEFT:
return GLUT_KEY_LEFT;
case KEYCODE_RIGHT:
//case KEYCODE_KP_RIGHT:
return GLUT_KEY_RIGHT;
case KEYCODE_NUM_LOCK:
return GLUT_KEY_NUM_LOCK;
case KEYCODE_LEFT_ALT:
return GLUT_KEY_ALT_L;
case KEYCODE_RIGHT_ALT:
return GLUT_KEY_ALT_R;
case KEYCODE_LEFT_SHIFT:
return GLUT_KEY_SHIFT_L;
case KEYCODE_RIGHT_SHIFT:
return GLUT_KEY_SHIFT_R;
case KEYCODE_LEFT_CTRL:
return GLUT_KEY_CTRL_L;
case KEYCODE_RIGHT_CTRL:
return GLUT_KEY_CTRL_R;
}
return 0;
}
unsigned char key_ascii(int qnxKeycode)
{
if (qnxKeycode >= KEYCODE_PC_KEYS && qnxKeycode <= UNICODE_PRIVATE_USE_AREA_LAST) {
switch (qnxKeycode) {
case KEYCODE_BACKSPACE:
return 0x0008;
case KEYCODE_TAB:
return 0x0009;
case KEYCODE_KP_ENTER:
case KEYCODE_RETURN:
return 0x000A;
case KEYCODE_ESCAPE:
return ESCAPE_BUTTON_KEY;
}
}
return qnxKeycode;
}
//From fg_main_x11
fg_time_t fgPlatformSystemTime ( void )
{
#ifdef CLOCK_MONOTONIC
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_nsec/1000000 + now.tv_sec*1000;
#elif defined(HAVE_GETTIMEOFDAY)
struct timeval now;
gettimeofday( &now, NULL );
return now.tv_usec/1000 + now.tv_sec*1000;
#endif
}
/*
* Does the magic required to relinquish the CPU until something interesting
* happens.
*/
void fgPlatformSleepForEvents( fg_time_t msec )
{
if(fgStructure.CurrentWindow && fgDisplay.pDisplay.event == NULL &&
bps_get_event(&fgDisplay.pDisplay.event, (int)msec) != BPS_SUCCESS) {
LOGW("BPS couldn't get event");
}
}
void handle_left_mouse(int x, int y, int height, int eventType, SFG_Window* window)
{
bool handled = false;
/* 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;
if (eventType == SCREEN_EVENT_MTOUCH_TOUCH || eventType == SCREEN_EVENT_MTOUCH_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 (eventType == SCREEN_EVENT_MTOUCH_TOUCH &&
(touchscreen.vpad.left || touchscreen.vpad.right || touchscreen.vpad.down || touchscreen.vpad.up)) {
touchscreen.vpad.on = true;
}
if (eventType == SCREEN_EVENT_MTOUCH_RELEASE) {
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));
}
}
handled = true;
}
}
/* Normal mouse events */
if (!handled && !touchscreen.vpad.on) {
window->State.MouseX = x;
window->State.MouseY = y;
if(eventType == SCREEN_EVENT_MTOUCH_MOVE) {
INVOKE_WCB(*window, Motion, (x, y));
} else if(FETCH_WCB(*window, Mouse)) {
touchscreen.in_mmotion = eventType == SCREEN_EVENT_MTOUCH_TOUCH;
int glutTouchType = eventType == SCREEN_EVENT_MTOUCH_TOUCH ? GLUT_DOWN : GLUT_UP;
INVOKE_WCB(*window, Mouse, (GLUT_LEFT_BUTTON, glutTouchType, x, y));
}
}
}
/*
* 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 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) {
//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;
}
void fgPlatformMainLoopPreliminaryWork ( void )
{
LOGI("fgPlatformMainLoopPreliminaryWork");
/* Request navigator events */
navigator_request_events(0);
/* 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);
}
void fgPlatformMainLoopPostWork ( void )
{
LOGI("fgPlatformMainLoopPostWork");
/* Stop all events */
screen_stop_events(fgDisplay.pDisplay.screenContext);
#ifndef __PLAYBOOK__
navigator_stop_events(0);
#endif
}
/* deal with work list items */
void fgPlatformInitWork(SFG_Window* window)
{
LOGI("fgPlatformInitWork");
/* 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
* is thus never received by client?
*/
}
void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask)
{
if (workMask & GLUT_FULL_SCREEN_WORK)
fgPlatformFullScreenToggle( window );
if (workMask & GLUT_POSITION_WORK)
fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos );
if (workMask & GLUT_SIZE_WORK)
fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight );
if (workMask & GLUT_ZORDER_WORK)
{
if (window->State.DesiredZOrder < 0)
fgPlatformPushWindow( window );
else
fgPlatformPopWindow( window );
}
}
void fgPlatformVisibilityWork(SFG_Window* window)
{
/* Visibility status of window should get updated in the window message handlers
* For now, none of these functions called below do anything, so don't worry
* about it
*/
SFG_Window *win = window;
switch (window->State.DesiredVisibility)
{
case DesireHiddenState:
fgPlatformHideWindow( window );
break;
case DesireIconicState:
/* Call on top-level window */
while (win->Parent)
win = win->Parent;
fgPlatformIconifyWindow( win );
break;
case DesireNormalState:
fgPlatformShowWindow( window );
break;
}
}

View File

@ -0,0 +1,144 @@
/*
* fg_state_blackberry.c
*
* BlackBerry-specific freeglut state query methods.
*
* Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
* Written by John F. Fay, <fayjf@sourceforge.net>
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include <stdio.h>
#include <screen/screen.h>
#include "fg_internal.h"
#include "egl/fg_state_egl.h"
//From fg_state_android.c
int fgPlatformGlutDeviceGet ( GLenum eWhat )
{
#ifndef __PLAYBOOK__
int deviceCount, i, value;
screen_device_t* devices;
#endif
switch( eWhat )
{
case GLUT_HAS_KEYBOARD:
/* BlackBerry has a keyboard, though it may be virtual. */
return 1;
case GLUT_HAS_MOUSE:
/* BlackBerry has a touchscreen. Consider it as a mouse since we have no guarantee
that a mouse will be used (in which case it's a simulator). */
return 1 ;
case GLUT_NUM_MOUSE_BUTTONS:
/* BlackBerry has a touchscreen, which we can consider a 1-button mouse at min.
Otherwise check for an actual mouse, else get max touch points. PlayBook does not support this. */
#ifndef __PLAYBOOK__
if(!screen_get_context_property_iv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICE_COUNT, &deviceCount)) {
devices = (screen_device_t*)calloc(deviceCount, sizeof(screen_device_t));
if(!screen_get_context_property_pv(fgDisplay.pDisplay.screenContext, SCREEN_PROPERTY_DEVICES, (void**)devices)) {
/* Check for a pointer */
for(i = 0; i < deviceCount; i++) {
if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) &&
value == SCREEN_EVENT_POINTER &&
!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_BUTTON_COUNT, &value)) {
free(devices);
return value;
}
}
/* Check for mtouch */
for(i = 0; i < deviceCount; i++) {
if(!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_TYPE, &value) &&
value == SCREEN_EVENT_MTOUCH_TOUCH &&
!screen_get_device_property_iv(devices[i], SCREEN_PROPERTY_MAXIMUM_TOUCH_ID, &value)) {
free(devices);
return value;
}
}
}
free(devices);
}
#endif
/* Backup, pretend it's a 1-button mouse */
return 1;
default:
fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
break;
}
/* And now -- the failure. */
return -1;
}
int fgPlatformGlutGet ( GLenum eWhat )
{
switch (eWhat) {
/* One full-screen window only */
case GLUT_WINDOW_X:
case GLUT_WINDOW_Y:
case GLUT_WINDOW_BORDER_WIDTH:
case GLUT_WINDOW_HEADER_HEIGHT:
return 0;
case GLUT_WINDOW_WIDTH:
case GLUT_WINDOW_HEIGHT:
{
if ( fgStructure.CurrentWindow == NULL )
return 0;
int size[2];
int orientation;
if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 )
return 0;
if ( screen_get_window_property_iv(fgStructure.CurrentWindow->Window.Handle, SCREEN_PROPERTY_ROTATION, &orientation) != 0 )
return 0;
int orientationDif = abs(orientation - fgStructure.CurrentWindow->State.pWState.originalRotation);
if (orientationDif == 90 || orientationDif == 270) {
/* Swap dim. if screen is rotated */
int tmp = size[0];
size[0] = size[1];
size[1] = tmp;
}
switch ( eWhat )
{
case GLUT_WINDOW_WIDTH:
return size[0];
case GLUT_WINDOW_HEIGHT:
return size[1];
}
break;
}
case GLUT_WINDOW_COLORMAP_SIZE:
/* 0 for RGBA/non-indexed mode */
/* Under BlackBerry and GLES more generally, no indexed-mode */
return 0;
default:
return fghPlatformGlutGetEGL(eWhat);
}
return -1;
}

View File

@ -0,0 +1,43 @@
/*
* fg_structure_blackberry.c
*
* Windows and menus need tree structure
*
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "fg_internal.h"
#include "egl/fg_structure_egl.h"
/**
* Initialize default platform-specific fields in SFG_Window
*/
void fgPlatformCreateWindow ( SFG_Window *window )
{
fghPlatformCreateWindowEGL(window);
memset(&(window->State.pWState), 0, sizeof(SFG_PlatformWindowState));
window->State.pWState.windowCovered = GL_FALSE;
#ifdef __PLAYBOOK__
window->State.pWState.keyboardOpen = GL_FALSE;
#endif
}

View File

@ -0,0 +1,309 @@
/*
* fg_window_blackberry.c
*
* Window management methods for BlackBerry
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Copied for Platform code by Evan Felix <karcaw at gmail.com>
* Copyright (C) 2012 Sylvain Beucler
* Copyright (C) 2013 Vincent Simonetti
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define FREEGLUT_BUILDING_LIB
#include <GL/freeglut.h>
#include "fg_internal.h"
#include "egl/fg_window_egl.h"
#include <screen/screen.h>
/*
* Opens a window. Requires a SFG_Window object created and attached
* to the freeglut structure. OpenGL context is created here.
*/
void fgPlatformOpenWindow( SFG_Window* window, const char* title,
GLboolean positionUse, int x, int y,
GLboolean sizeUse, int w, int h,
GLboolean gameMode, GLboolean isSubWindow )
{
/* TODO: only one full-screen window possible? */
if (fgDisplay.pDisplay.single_native_window != NULL) {
fgWarning("You can't have more than one window on BlackBerry");
return;
}
/* Create window */
screen_window_t sWindow;
if (screen_create_window(&sWindow, fgDisplay.pDisplay.screenContext)) {
fgError("Could not create window");
return;
}
fgDisplay.pDisplay.single_native_window = sWindow;
/* Choose config and screen format */
fghChooseConfig(&window->Window.pContext.egl.Config);
int screenFormat = SCREEN_FORMAT_RGBA8888; //Only SCREEN_FORMAT_RGBA8888 and SCREEN_FORMAT_RGB565 are supported. See fg_window_egl for more info
int configAttri;
#define EGL_QUERY_COMP(att, comp) (eglGetConfigAttrib(fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Config, att, &configAttri) == GL_TRUE && (configAttri comp))
if(EGL_QUERY_COMP(EGL_ALPHA_SIZE, <= 0) && EGL_QUERY_COMP(EGL_RED_SIZE, <= 5) &&
EGL_QUERY_COMP(EGL_GREEN_SIZE, <= 6) && EGL_QUERY_COMP(EGL_BLUE_SIZE, <= 5)) {
screenFormat = SCREEN_FORMAT_RGB565;
}
#undef EGL_QUERY_COMP
/* Set window properties */
int orientation = atoi(getenv("ORIENTATION"));
#ifdef GL_ES_VERSION_2_0
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 | SCREEN_USAGE_ROTATION;
#endif
#if !defined(__X86__) && !defined(__PLAYBOOK__)
screenUsage |= SCREEN_USAGE_DISPLAY; // Physical device copy directly into physical display
#endif
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_FORMAT, &screenFormat)) {
screen_destroy_window(sWindow);
fgError("Could not set window format");
return;
}
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_USAGE, &screenUsage)) {
screen_destroy_window(sWindow);
fgError("Could not set window usage");
return;
}
int value[2];
/* Uncomment when multiple windows are supported
if(positionUse) {
value[0] = x;
value[1] = y;
if (screen_set_window_property_iv(sWindow, SCREEN_PROPERTY_POSITION, value)) {
screen_destroy_window(sWindow);
fgError("Could not set window position");
return;
}
}*/
if(sizeUse) {
/* Uncomment when multiple windows are supported
value[0] = w;
value[1] = h;
*/
//TEMP until ^^ is uncommented
if (screen_get_window_property_iv(sWindow, SCREEN_PROPERTY_BUFFER_SIZE, value)) {
screen_destroy_window(sWindow);
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;
}
window->State.pWState.originalRotation = orientation;
/* 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)) {
screen_destroy_window(sWindow);
fgError("Could not create window buffers");
return;
}
/* Save window and set state */
window->Window.Handle = sWindow;
window->State.WorkMask |= GLUT_INIT_WORK;
window->State.IsFullscreen = GL_TRUE; //XXX Always fullscreen for now
/* Create context */
window->Window.Context = EGL_NO_CONTEXT;
if( fgState.UseCurrentContext == GL_TRUE )
window->Window.Context = eglGetCurrentContext();
if( window->Window.Context == EGL_NO_CONTEXT )
window->Window.Context = fghCreateNewContextEGL(window);
/* Create EGL window */
fghPlatformOpenWindowEGL(window);
window->State.Visible = GL_TRUE;
}
void fgPlatformFlushCommands()
{
if(screen_flush_context(fgDisplay.pDisplay.screenContext, 0)) {
fgWarning("Could not flush screen context");
}
}
void fgPlatformRotateWindow(SFG_Window* window, int rotation)
{
if(screen_set_window_property_iv(window->Window.Handle, SCREEN_PROPERTY_ROTATION, &rotation)) {
fgWarning("Could not set window rotation");
}
}
/*
* Request a window resize
*/
void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
{
fprintf(stderr, "fgPlatformReshapeWindow: STUB\n");
}
/*
* Closes a window, destroying the frame and OpenGL context
*/
void fgPlatformCloseWindow( SFG_Window* window )
{
fghPlatformCloseWindowEGL(window);
screen_destroy_window((screen_window_t)window->Window.Handle);
}
/*
* This function makes the specified window visible
*/
void fgPlatformShowWindow( void )
{
fprintf(stderr, "fgPlatformShowWindow: STUB\n");
}
/*
* This function hides the specified window
*/
void fgPlatformHideWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformHideWindow: STUB\n");
}
/*
* Iconify the specified window (top-level windows only)
*/
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");
}
/*
* Set the current window's title
*/
void fgPlatformGlutSetWindowTitle( const char* title )
{
fprintf(stderr, "fgPlatformGlutSetWindowTitle: STUB\n");
}
/*
* Set the current window's iconified title
*/
void fgPlatformGlutSetIconTitle( const char* title )
{
fprintf(stderr, "fgPlatformGlutSetIconTitle: STUB\n");
}
/*
* Change the specified window's position
*/
void fgPlatformPositionWindow( SFG_Window *window, int x, int y )
{
fprintf(stderr, "fgPlatformPositionWindow: STUB\n");
}
/*
* Lowers the specified window (by Z order change)
*/
void fgPlatformPushWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformPushWindow: STUB\n");
}
/*
* Raises the specified window (by Z order change)
*/
void fgPlatformPopWindow( SFG_Window *window )
{
fprintf(stderr, "fgPlatformPopWindow: STUB\n");
}
/*
* Toggle the window's full screen state.
*/
void fgPlatformFullScreenToggle( SFG_Window *win )
{
fprintf(stderr, "fgPlatformFullScreenToggle: STUB\n");
}

View File

@ -30,15 +30,29 @@ int fghChooseConfig(EGLConfig* config) {
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#ifdef GL_ES_VERSION_2_0
/*
* Khronos does not specify a EGL_OPENGL_ES3_BIT outside of the OpenGL extension "EGL_KHR_create_context". There are numerous references on the internet that
* say to use EGL_OPENGL_ES3_BIT, followed by many saying they can't find it in any headers. In fact, the offical updated specification for EGL does not have
* any references to OpenGL ES 3.0. Tests have shown that EGL_OPENGL_ES2_BIT will work with ES 3.0.
*/
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#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
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
#else
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
#endif
#ifdef TARGET_HOST_BLACKBERRY
/* Only 888 and 565 seem to work. Based on
http://qt.gitorious.org/qt/qtbase/source/893deb1a93021cdfabe038cdf1869de33a60cbc9:src/plugins/platforms/qnx/qqnxglcontext.cpp and
https://twitter.com/BlackBerryDev/status/380720927475912706 */
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
#else
EGL_BLUE_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_RED_SIZE, 1,
#endif
EGL_ALPHA_SIZE, (fgState.DisplayMode & GLUT_ALPHA) ? 1 : 0,
EGL_DEPTH_SIZE, (fgState.DisplayMode & GLUT_DEPTH) ? 1 : 0,
EGL_STENCIL_SIZE, (fgState.DisplayMode & GLUT_STENCIL) ? 1 : 0,
@ -46,10 +60,10 @@ int fghChooseConfig(EGLConfig* config) {
EGL_SAMPLES, (fgState.DisplayMode & GLUT_MULTISAMPLE) ? fgState.SampleNumber : 0,
EGL_NONE
};
EGLint num_config;
if (!eglChooseConfig(fgDisplay.pDisplay.egl.Display,
attribs, config, 1, &num_config)) {
attribs, config, 1, &num_config)) {
fgWarning("eglChooseConfig: error %x\n", eglGetError());
return 0;
}
@ -67,7 +81,7 @@ EGLContext fghCreateNewContextEGL( SFG_Window* window ) {
EGLConfig eglConfig = window->Window.pContext.egl.Config;
/* Ensure OpenGLES 2.0 context */
static const EGLint ctx_attribs[] = {
static EGLint ctx_attribs[] = {
#ifdef GL_ES_VERSION_2_0
EGL_CONTEXT_CLIENT_VERSION, 2,
#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
@ -75,6 +89,14 @@ EGLContext fghCreateNewContextEGL( SFG_Window* window ) {
#endif
EGL_NONE
};
#ifdef GL_ES_VERSION_2_0
/*
* As GLES 3.0 is backwards compatible with GLES 2.0, we set 2.0 as default unless the user states a different version.
* This updates the context attributes and lets us check that the correct version was set when we query it after creation.
*/
int gles2Ver = fgState.MajorVersion <= 2 ? 2 : fgState.MajorVersion;
ctx_attribs[1] = gles2Ver;
#endif
context = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, ctx_attribs);
if (context == EGL_NO_CONTEXT) {
fgWarning("Cannot initialize EGL context, err=%x\n", eglGetError());
@ -83,7 +105,7 @@ EGLContext fghCreateNewContextEGL( SFG_Window* window ) {
EGLint ver = -1;
eglQueryContext(fgDisplay.pDisplay.egl.Display, context, EGL_CONTEXT_CLIENT_VERSION, &ver);
#ifdef GL_ES_VERSION_2_0
if (ver != 2)
if (ver != gles2Ver)
#else
if (ver != 1)
#endif
@ -94,11 +116,13 @@ EGLContext fghCreateNewContextEGL( SFG_Window* window ) {
void fgPlatformSetWindow ( SFG_Window *window )
{
if (eglMakeCurrent(fgDisplay.pDisplay.egl.Display,
window->Window.pContext.egl.Surface,
window->Window.pContext.egl.Surface,
window->Window.Context) == EGL_FALSE)
fgError("eglMakeCurrent: err=%x\n", eglGetError());
if ( window != fgStructure.CurrentWindow && window) {
if (eglMakeCurrent(fgDisplay.pDisplay.egl.Display,
window->Window.pContext.egl.Surface,
window->Window.pContext.egl.Surface,
window->Window.Context) == EGL_FALSE)
fgError("eglMakeCurrent: err=%x\n", eglGetError());
}
}
/*
@ -127,9 +151,28 @@ void fghPlatformOpenWindowEGL( SFG_Window* window )
*/
void fghPlatformCloseWindowEGL( SFG_Window* window )
{
eglMakeCurrent(fgDisplay.pDisplay.egl.Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
/* Based on fg_window_mswin fgPlatformCloseWindow */
if( fgStructure.CurrentWindow == window )
eglMakeCurrent(fgDisplay.pDisplay.egl.Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (window->Window.Context != EGL_NO_CONTEXT) {
eglDestroyContext(fgDisplay.pDisplay.egl.Display, window->Window.Context);
/* Step through the list of windows. If the rendering context is not being used by another window, then delete it */
{
GLboolean used = GL_FALSE;
SFG_Window *iter;
for( iter = (SFG_Window*)fgStructure.Windows.First;
iter && used == GL_FALSE;
iter = (SFG_Window*)iter->Node.Next)
{
if( (iter->Window.Context == window->Window.Context) &&
(iter != window) )
used = GL_TRUE;
}
if( !used )
eglDestroyContext(fgDisplay.pDisplay.egl.Display, window->Window.Context);
}
window->Window.Context = EGL_NO_CONTEXT;
}

View File

@ -110,7 +110,7 @@ void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName
int i, j, argc = *pargc;
{
/* check if GLUT_FPS env var is set */
/* check if GLUT_FPS env var is set */
const char *fps = getenv( "GLUT_FPS" );
if( fps )
@ -229,7 +229,7 @@ void fgDeinitialize( void )
return;
}
/* If we're in game mode, we want to leave game mode */
/* If we're in game mode, we want to leave game mode */
if( fgStructure.GameModeWindow ) {
glutLeaveGameMode();
}
@ -237,7 +237,7 @@ void fgDeinitialize( void )
/* If there was a menu created, destroy the rendering context */
if( fgStructure.MenuContext )
{
fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
free( fgStructure.MenuContext );
fgStructure.MenuContext = NULL;
}
@ -256,9 +256,9 @@ void fgDeinitialize( void )
free( timer );
}
fgPlatformDeinitialiseInputDevices ();
fgPlatformDeinitialiseInputDevices ();
fgState.MouseWheelTicks = 0;
fgState.MouseWheelTicks = 0;
fgState.MajorVersion = 1;
fgState.MinorVersion = 0;
@ -310,7 +310,7 @@ void fgDeinitialize( void )
fgState.ProgramName = NULL;
}
fgPlatformCloseDisplay ();
fgPlatformCloseDisplay ();
fgState.Initialised = GL_FALSE;
}
@ -342,7 +342,7 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
fgCreateStructure( );
fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
/*
* Have the display created now. If there wasn't a "-display"

View File

@ -45,6 +45,9 @@
#elif defined (__ANDROID__)
# define TARGET_HOST_ANDROID 1
#elif defined (__QNXNTO__) || defined (__PLAYBOOK__)
# define TARGET_HOST_BLACKBERRY 1
#elif defined(__posix__) || defined(__unix__) || defined(__linux__) || defined(__sun)
# define TARGET_HOST_POSIX_X11 1
@ -68,6 +71,14 @@
# define TARGET_HOST_MS_WINDOWS 0
#endif
#ifndef TARGET_HOST_ANDROID
# define TARGET_HOST_ANDROID 0
#endif
#ifndef TARGET_HOST_BLACKBERRY
# define TARGET_HOST_BLACKBERRY 0
#endif
#ifndef TARGET_HOST_POSIX_X11
# define TARGET_HOST_POSIX_X11 0
#endif
@ -184,6 +195,9 @@
#if TARGET_HOST_ANDROID
#include "android/fg_internal_android.h"
#endif
#if TARGET_HOST_BLACKBERRY
#include "blackberry/fg_internal_blackberry.h"
#endif
/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
@ -372,7 +386,7 @@ struct tagSFG_Context
int DoubleBuffered; /* Treat the window as double-buffered */
/* When drawing geometry to vertex attribute buffers, user specifies
/* When drawing geometry to vertex attribute buffers, user specifies
* the attribute indices for vertices, normals and/or texture coords
* to freeglut. Those are stored here
*/

View File

@ -106,7 +106,7 @@ void fghContextCreationError( void )
*/
void fgSetWindow ( SFG_Window *window )
{
fgPlatformSetWindow ( window );
fgPlatformSetWindow ( window );
fgStructure.CurrentWindow = window;
}
@ -158,7 +158,7 @@ void fgCloseWindow( SFG_Window* window )
if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID)
glutLeaveGameMode();
fgPlatformCloseWindow ( window );
fgPlatformCloseWindow ( window );
}
@ -335,7 +335,7 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
if( ! fgStructure.CurrentWindow->Parent )
{
fgPlatformGlutSetWindowTitle ( title );
fgPlatformGlutSetWindowTitle ( title );
}
}
@ -349,7 +349,7 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
if( ! fgStructure.CurrentWindow->Parent )
{
fgPlatformGlutSetIconTitle ( title );
fgPlatformGlutSetIconTitle ( title );
}
}
@ -445,7 +445,7 @@ void FGAPIENTRY glutFullScreen( void )
}
if (!win->State.IsFullscreen)
win->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
win->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
}
/*