reimplementable) Main/fg_os.cxx file.
#include <map>
#include <vector>
-#include <plib/pu.h>
-
#include "ATC.hxx"
#include "transmission.hxx"
# include <windows.h>
#endif
-#include FG_GLUT_H // needed before pu.h
-
-#include <plib/pu.h> // plib include
+#include <Main/fg_os.hxx> // must come before pu.h
+#include <plib/pu.h>
#include <simgear/structure/exception.hxx>
# include <windows.h>
#endif
-#include FG_GLUT_H // needed before pu.h
+#include <Main/fg_os.hxx> // needed before pu.h
#include <plib/pu.h> // plib include
#include <FDM/flight.hxx>
# include <windows.h>
#endif
-#include FG_GLUT_H
+#include <Main/fg_os.hxx>
#if defined(FX) && defined(XMESA)
# include <GL/xmesa.h>
// if the little rodent is moved NHV
static int _mVtoggle = 0;
-// we break up the glutGetModifiers return mask
-// once per loop and stash what we need in these
-static int glut_active_shift = 0;
-static int glut_active_ctrl = 0;
-static int glut_active_alt = 0;
-
static int MOUSE_XSIZE = 0;
static int MOUSE_YSIZE = 0;
};
static inline int left_button( void ) {
- return( last_buttons & (1 << GLUT_LEFT_BUTTON) );
+ return( last_buttons & (1 << MOUSE_BUTTON_LEFT) );
}
static inline int middle_button( void ) {
- return( last_buttons & (1 << GLUT_MIDDLE_BUTTON) );
+ return( last_buttons & (1 << MOUSE_BUTTON_MIDDLE) );
}
static inline int right_button( void ) {
- return( last_buttons & (1 << GLUT_RIGHT_BUTTON) );
+ return( last_buttons & (1 << MOUSE_BUTTON_RIGHT) );
}
static inline void set_goal_view_offset( float offset )
#if defined(WIN32)
switch (mouse_mode) {
case MOUSE_POINTER:
- glutSetCursor(GLUT_CURSOR_INHERIT);
+ fgSetMouseCursor(MOUSE_CURSOR_INHERIT);
break;
case MOUSE_YOKE:
- glutSetCursor(GLUT_CURSOR_CROSSHAIR);
+ fgSetMouseCursor(MOUSE_CURSOR_CROSSHAIR);
break;
case MOUSE_VIEW:
- glutSetCursor(GLUT_CURSOR_LEFT_RIGHT);
+ fgSetMouseCursor(MOUSE_CURSOR_LEFT_RIGHT);
break;
}
#endif
#if defined(X_CURSOR_TWEAKS)
- glutWarpPointer( MOUSE_XSIZE/2,
- MOUSE_YSIZE/2);
+ fgWarpMouse( MOUSE_XSIZE/2, MOUSE_YSIZE/2 );
#endif
}
{
mouse_active = 0;
#if defined(WIN32_CURSOR_TWEAKS)
- glutSetCursor(GLUT_CURSOR_NONE);
+ fgSetMouseCursor(MOUSE_CURSOR_NONE);
#elif defined(X_CURSOR_TWEAKS)
- glutWarpPointer( MOUSE_XSIZE,
- MOUSE_YSIZE);
+ fgWarpMouse( MOUSE_XSIZE, MOUSE_YSIZE );
#endif
}
// Call with FALSE to init and TRUE to restore
void BusyCursor( int restore )
{
- static GLenum cursor = (GLenum) 0;
+ static int cursor = MOUSE_CURSOR_POINTER;
if( restore ) {
- glutSetCursor(cursor);
+ fgSetMouseCursor(cursor);
} else {
- cursor = (GLenum) glutGet( (GLenum) GLUT_WINDOW_CURSOR );
+ cursor = fgGetMouseCursor();
#if defined(WIN32_CURSOR_TWEAKS)
TurnCursorOn();
#endif
- glutSetCursor( GLUT_CURSOR_WAIT );
+ fgSetMouseCursor( MOUSE_CURSOR_WAIT );
}
}
_mVtoggle = 0;
Quat0();
build_rotmatrix(GuiQuat_mat, curGuiQuat);
- glutSetCursor(GLUT_CURSOR_INHERIT);
+ fgSetMouseCursor(MOUSE_CURSOR_POINTER);
// Is this necessary ??
#if defined(FG_OLD_MENU)
if( !gui_menu_on ) TurnCursorOff();
#endif
- glutWarpPointer( _savedX, _savedY );
+ fgWarpMouse( _savedX, _savedY );
}
set_goal_view_offset(0.0);
set_view_offset(0.0);
}
#endif
puMouse ( x, y ) ;
- glutPostRedisplay () ;
+ fgRequestRedraw () ;
} else {
if( x == _mX && y == _mY)
return;
}
}
if( need_warp)
- glutWarpPointer(x, y);
+ fgWarpMouse(x, y);
// Record the new mouse position.
_mX = x;
void guiMouseFunc(int button, int updown, int x, int y)
{
- int glutModifiers;
// private MOUSE_VIEW state variables
// to allow alternate left clicks in MOUSE_VIEW mode
static float _quat[4];
static double _view_offset;
- glutModifiers = glutGetModifiers();
- glut_active_shift = glutModifiers & GLUT_ACTIVE_SHIFT;
- glut_active_ctrl = glutModifiers & GLUT_ACTIVE_CTRL;
- glut_active_alt = glutModifiers & GLUT_ACTIVE_ALT;
-
// Was the left button pressed?
- if (updown == GLUT_DOWN ) {
- if( button == GLUT_LEFT_BUTTON)
+ if ( updown == MOUSE_BUTTON_DOWN ) {
+ if( button == MOUSE_BUTTON_LEFT)
{
switch (mouse_mode) {
case MOUSE_POINTER:
set_view_tilt(0.0);
#endif
}
- glutWarpPointer( x , y);
+ fgWarpMouse( x , y);
build_rotmatrix(GuiQuat_mat, curGuiQuat);
_mVtoggle = ~_mVtoggle;
break;
}
- } else if ( button == GLUT_RIGHT_BUTTON) {
+ } else if ( button == MOUSE_BUTTON_RIGHT) {
switch (mouse_mode) {
case MOUSE_POINTER:
x = _mX - (int)(get_aileron() * aileron_sensitivity);
y = _mY - (int)(get_elevator() * elevator_sensitivity);
- glutSetCursor(GLUT_CURSOR_CROSSHAIR);
+ fgSetMouseCursor(MOUSE_CURSOR_CROSSHAIR);
break;
case MOUSE_YOKE:
Quat0();
build_rotmatrix(GuiQuat_mat, curGuiQuat);
// #endif
- glutSetCursor(GLUT_CURSOR_LEFT_RIGHT);
+ fgSetMouseCursor(MOUSE_CURSOR_LEFTRIGHT);
break;
case MOUSE_VIEW:
set_view_tilt(0.0);
#endif // NO_SMOOTH_MOUSE_VIEW
#endif // RESET_VIEW_ON_LEAVING_MOUSE_VIEW
- glutSetCursor(GLUT_CURSOR_INHERIT);
+ fgSetMouseCursor(MOUSE_CURSOR_POINTER);
#if defined(FG_OLD_MENU)
#if defined(WIN32_CURSOR_TWEAKS_OFF)
#endif // FG_OLD_MENU
break;
} // end switch (mouse_mode)
- glutWarpPointer( x, y );
+ fgWarpMouse( x, y );
} // END RIGHT BUTTON
- } // END UPDOWN == GLUT_DOWN
+ } // END MOUSE DOWN
- // Note which button is pressed.
- if ( updown == GLUT_DOWN ) {
+ // Update the button state
+ if ( updown == MOUSE_BUTTON_DOWN ) {
last_buttons |= ( 1 << button ) ;
} else {
last_buttons &= ~( 1 << button ) ;
// If we're in pointer mode, let PUI
// know what's going on.
if (mouse_mode == MOUSE_POINTER) {
- if (!puMouse (button, updown, x,y)) {
+ if (!puMouse (button, updown , x,y)) {
if ( globals->get_current_panel() != NULL ) {
globals->get_current_panel()->doMouseAction(button, updown, x, y);
}
_mX = x;
_mY = y;
- glutPostRedisplay ();
+ fgRequestRedraw ();
}
#include STL_STRING
#include <vector>
-#include FG_GLUT_H
-
-#include <plib/pu.h>
-
#include <simgear/compiler.h>
#include <simgear/constants.h>
SG_USING_STD(string);
SG_USING_STD(vector);
+void mouseClickHandler(int button, int updown, int x, int y);
+void mouseMotionHandler(int x, int y);
+void keyHandler(int key, int keymod, int mousex, int mousey);
\f
////////////////////////////////////////////////////////////////////////
_init_joystick();
_init_mouse();
- glutKeyboardFunc(GLUTkey);
- glutKeyboardUpFunc(GLUTkeyup);
- glutSpecialFunc(GLUTspecialkey);
- glutSpecialUpFunc(GLUTspecialkeyup);
- glutMouseFunc (GLUTmouse);
- glutMotionFunc (GLUTmotion);
- glutPassiveMotionFunc (GLUTmotion);
+ fgRegisterKeyHandler(keyHandler);
+ fgRegisterMouseClickHandler(mouseClickHandler);
+ fgRegisterMouseMotionHandler(mouseMotionHandler);
}
void
button &b = _key_bindings[k];
// Key pressed.
- if (modifiers&FG_MOD_UP == 0) {
+ if (modifiers&KEYMOD_RELEASED == 0) {
SG_LOG( SG_INPUT, SG_DEBUG, "User pressed key " << k
<< " with modifiers " << modifiers );
if (!b.last_state || b.is_repeatable) {
// Use the old, default actions.
SG_LOG( SG_INPUT, SG_DEBUG, "(No user binding.)" );
- if (modifiers&FG_MOD_UP)
- return;
-
- // everything after here will be removed sooner or later...
-
- if (modifiers & FG_MOD_SHIFT) {
-
- switch (k) {
- case 72: // H key
- HUD_brightkey( true );
- return;
- case 73: // I key
- // Minimal Hud
- fgHUDInit2(¤t_aircraft);
- return;
- }
-
-
- } else {
- SG_LOG( SG_INPUT, SG_DEBUG, "" );
- switch (k) {
- case 104: // h key
- HUD_masterswitch( true );
- return;
- case 105: // i key
- fgHUDInit(¤t_aircraft); // normal HUD
- return;
-
-// START SPECIALS
-
- case 256+GLUT_KEY_F6: // F6 toggles Autopilot target location
- if ( strcmp( heading_enabled->getStringValue(),
- "true-heading-hold" ) != 0 ) {
- heading_enabled->setStringValue( "true-heading-hold" );
- } else {
- heading_enabled->setStringValue( "" );
- }
- return;
- }
-
-// END SPECIALS
-
- }
}
void
FGInput::doMouseClick (int b, int updown, int x, int y)
{
- int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
+ int modifiers = fgGetKeyModifiers();
mouse &m = _mouse_bindings[0];
mouse_mode &mode = m.modes[m.current_mode];
// Let the property manager know.
if (b >= 0 && b < MAX_MOUSE_BUTTONS)
- m.mouse_button_nodes[b]->setBoolValue(updown == GLUT_DOWN);
+ m.mouse_button_nodes[b]->setBoolValue(updown == MOUSE_BUTTON_DOWN);
// Pass on to PUI and the panel if
// requested, and return if one of
void
FGInput::doMouseMotion (int x, int y)
{
- int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
+ int modifiers = fgGetKeyModifiers();
int xsize = fgGetInt("/sim/startup/xsize", 800);
int ysize = fgGetInt("/sim/startup/ysize", 600);
}
if (need_warp)
- glutWarpPointer(x, y);
+ fgWarpMouse(x, y);
}
m.x = x;
m.y = y;
_key_bindings[index].bindings->clear();
_key_bindings[index].is_repeatable = keys[i]->getBoolValue("repeatable");
- _read_bindings(keys[i], _key_bindings[index].bindings, FG_MOD_NONE);
+ _read_bindings(keys[i], _key_bindings[index].bindings, KEYMOD_NONE);
}
}
maxRange[j] = axis_node->getDoubleValue("max-range", maxRange[j]);
center[j] = axis_node->getDoubleValue("center", center[j]);
- _read_bindings(axis_node, a.bindings, FG_MOD_NONE);
+ _read_bindings(axis_node, a.bindings, KEYMOD_NONE);
// Initialize the virtual axis buttons.
_init_button(axis_node->getChild("low"), a.low, "low");
}
//
-// Map of all known GLUT cursor names
+// Map of all known cursor names
+// This used to contain all the Glut cursors, but those are
+// not defined by other toolkits. It now supports only the cursor
+// images we actually use, in the interest of portability. Someday,
+// it would be cool to write an OpenGL cursor renderer, with the
+// cursors defined as textures referenced in the property tree. This
+// list could then be eliminated. -Andy
//
struct {
const char * name;
int cursor;
} mouse_cursor_map[] = {
- { "right-arrow", GLUT_CURSOR_RIGHT_ARROW },
- { "left-arrow", GLUT_CURSOR_LEFT_ARROW },
- { "info", GLUT_CURSOR_INFO },
- { "destroy", GLUT_CURSOR_DESTROY },
- { "help", GLUT_CURSOR_HELP },
- { "cycle", GLUT_CURSOR_CYCLE },
- { "spray", GLUT_CURSOR_SPRAY },
- { "wait", GLUT_CURSOR_WAIT },
- { "text", GLUT_CURSOR_TEXT },
- { "crosshair", GLUT_CURSOR_CROSSHAIR },
- { "up-down", GLUT_CURSOR_UP_DOWN },
- { "left-right", GLUT_CURSOR_LEFT_RIGHT },
- { "top-side", GLUT_CURSOR_TOP_SIDE },
- { "bottom-side", GLUT_CURSOR_BOTTOM_SIDE },
- { "left-side", GLUT_CURSOR_LEFT_SIDE },
- { "right-side", GLUT_CURSOR_RIGHT_SIDE },
- { "top-left-corner", GLUT_CURSOR_TOP_LEFT_CORNER },
- { "top-right-corner", GLUT_CURSOR_TOP_RIGHT_CORNER },
- { "bottom-right-corner", GLUT_CURSOR_BOTTOM_RIGHT_CORNER },
- { "bottom-left-corner", GLUT_CURSOR_BOTTOM_LEFT_CORNER },
- { "inherit", GLUT_CURSOR_INHERIT },
- { "none", GLUT_CURSOR_NONE },
- { "full-crosshair", GLUT_CURSOR_FULL_CROSSHAIR },
+ { "none", MOUSE_CURSOR_NONE },
+ { "inherit", MOUSE_CURSOR_POINTER },
+ { "wait", MOUSE_CURSOR_WAIT },
+ { "crosshair", MOUSE_CURSOR_CROSSHAIR },
+ { "left-right", MOUSE_CURSOR_LEFTRIGHT },
{ 0, 0 }
};
-
-
void
FGInput::_init_mouse ()
{
SGPropertyNode * mode_node = mouse_node->getChild("mode", j, true);
const char * cursor_name =
mode_node->getStringValue("cursor", "inherit");
- m.modes[j].cursor = GLUT_CURSOR_INHERIT;
+ m.modes[j].cursor = MOUSE_CURSOR_POINTER;
for (k = 0; mouse_cursor_map[k].name != 0; k++) {
if (!strcmp(mouse_cursor_map[k].name, cursor_name)) {
m.modes[j].cursor = mouse_cursor_map[k].cursor;
// Read the axis bindings for this mode
_read_bindings(mode_node->getChild("x-axis", 0, true),
m.modes[j].x_bindings,
- FG_MOD_NONE);
+ KEYMOD_NONE);
_read_bindings(mode_node->getChild("y-axis", 0, true),
m.modes[j].y_bindings,
- FG_MOD_NONE);
+ KEYMOD_NONE);
}
}
}
b.is_repeatable = node->getBoolValue("repeatable", b.is_repeatable);
// Get the bindings for the button
- _read_bindings(node, b.bindings, FG_MOD_NONE);
+ _read_bindings(node, b.bindings, KEYMOD_NONE);
}
}
void
FGInput::_update_joystick (double dt)
{
- int modifiers = FG_MOD_NONE; // FIXME: any way to get the real ones?
+ int modifiers = KEYMOD_NONE; // FIXME: any way to get the real ones?
int buttons;
// float js_val, diff;
float axis_values[MAX_JOYSTICK_AXES];
if (mode != m.current_mode) {
m.current_mode = mode;
if (mode >= 0 && mode < m.nModes) {
- glutSetCursor(m.modes[mode].cursor);
+ fgSetMouseCursor(m.modes[mode].cursor);
m.x = fgGetInt("/sim/startup/xsize", 800) / 2;
m.y = fgGetInt("/sim/startup/ysize", 600) / 2;
- glutWarpPointer(m.x, m.y);
+ fgWarpMouse(m.x, m.y);
} else {
SG_LOG(SG_INPUT, SG_DEBUG, "Mouse mode " << mode << " out of range");
- glutSetCursor(GLUT_CURSOR_INHERIT);
+ fgSetMouseCursor(MOUSE_CURSOR_POINTER);
}
}
}
// The release event is never repeated.
if (b.last_state) {
SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
- for (unsigned int k = 0; k < b.bindings[modifiers|FG_MOD_UP].size(); k++)
- b.bindings[modifiers|FG_MOD_UP][k]->fire(x, y);
+ for (unsigned int k = 0; k < b.bindings[modifiers|KEYMOD_RELEASED].size(); k++)
+ b.bindings[modifiers|KEYMOD_RELEASED][k]->fire(x, y);
}
}
// Read nested bindings for modifiers
if (node->getChild("mod-up") != 0)
_read_bindings(node->getChild("mod-up"), binding_list,
- modifiers|FG_MOD_UP);
+ modifiers|KEYMOD_RELEASED);
if (node->getChild("mod-shift") != 0)
_read_bindings(node->getChild("mod-shift"), binding_list,
- modifiers|FG_MOD_SHIFT);
+ modifiers|KEYMOD_SHIFT);
if (node->getChild("mod-ctrl") != 0)
_read_bindings(node->getChild("mod-ctrl"), binding_list,
- modifiers|FG_MOD_CTRL);
+ modifiers|KEYMOD_CTRL);
if (node->getChild("mod-alt") != 0)
_read_bindings(node->getChild("mod-alt"), binding_list,
- modifiers|FG_MOD_ALT);
+ modifiers|KEYMOD_ALT);
}
return b.bindings[modifiers];
// Alt-Gr is CTRL+ALT
- else if (modifiers&(FG_MOD_CTRL|FG_MOD_ALT))
- return _find_key_bindings(k, modifiers&~(FG_MOD_CTRL|FG_MOD_ALT));
+ else if (modifiers&(KEYMOD_CTRL|KEYMOD_ALT))
+ return _find_key_bindings(k, modifiers&~(KEYMOD_CTRL|KEYMOD_ALT));
// Try removing the control modifier
// for control keys.
- else if ((modifiers&FG_MOD_CTRL) && iscntrl(kc))
- return _find_key_bindings(k, modifiers&~FG_MOD_CTRL);
+ else if ((modifiers&KEYMOD_CTRL) && iscntrl(kc))
+ return _find_key_bindings(k, modifiers&~KEYMOD_CTRL);
// Try removing shift modifier
// for upper case or any punctuation
// (since different keyboards will
// shift different punctuation types)
- else if ((modifiers&FG_MOD_SHIFT) && (isupper(kc) || ispunct(kc)))
- return _find_key_bindings(k, modifiers&~FG_MOD_SHIFT);
+ else if ((modifiers&KEYMOD_SHIFT) && (isupper(kc) || ispunct(kc)))
+ return _find_key_bindings(k, modifiers&~KEYMOD_SHIFT);
// Try removing alt modifier for
// high-bit characters.
- else if ((modifiers&FG_MOD_ALT) && k >= 128 && k < 256)
- return _find_key_bindings(k, modifiers&~FG_MOD_ALT);
+ else if ((modifiers&KEYMOD_ALT) && k >= 128 && k < 256)
+ return _find_key_bindings(k, modifiers&~KEYMOD_ALT);
// Give up and return the empty vector.
else
FGInput::button::~button ()
{
// FIXME: memory leak
-// for (int i = 0; i < FG_MOD_MAX; i++)
+// for (int i = 0; i < KEYMOD_MAX; i++)
// for (int j = 0; i < bindings[i].size(); j++)
// delete bindings[i][j];
}
FGInput::axis::~axis ()
{
-// for (int i = 0; i < FG_MOD_MAX; i++)
+// for (int i = 0; i < KEYMOD_MAX; i++)
// for (int j = 0; i < bindings[i].size(); j++)
// delete bindings[i][j];
}
////////////////////////////////////////////////////////////////////////
FGInput::mouse_mode::mouse_mode ()
- : cursor(GLUT_CURSOR_INHERIT),
+ : cursor(MOUSE_CURSOR_POINTER),
constrained(false),
pass_through(false),
buttons(0)
FGInput::mouse_mode::~mouse_mode ()
{
// FIXME: memory leak
-// for (int i = 0; i < FG_MOD_MAX; i++) {
+// for (int i = 0; i < KEYMOD_MAX; i++) {
// int j;
// for (j = 0; i < x_bindings[i].size(); j++)
// delete bindings[i][j];
delete [] modes;
}
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of GLUT callbacks.
-////////////////////////////////////////////////////////////////////////
-
-
-/**
- * Construct the modifiers.
- */
-static inline int get_mods ()
-{
- int glut_modifiers = glutGetModifiers();
- int modifiers = 0;
-
- if (glut_modifiers & GLUT_ACTIVE_SHIFT)
- modifiers |= FGInput::FG_MOD_SHIFT;
- if (glut_modifiers & GLUT_ACTIVE_CTRL)
- modifiers |= FGInput::FG_MOD_CTRL;
- if (glut_modifiers & GLUT_ACTIVE_ALT)
- modifiers |= FGInput::FG_MOD_ALT;
-
- return modifiers;
-}
-
-
-\f
////////////////////////////////////////////////////////////////////////
-// GLUT C callbacks.
+// Implementation of OS callbacks.
////////////////////////////////////////////////////////////////////////
-void
-GLUTkey(unsigned char k, int x, int y)
+void keyHandler(int key, int keymod, int mousex, int mousey)
{
- // Give PUI a chance to grab it first.
- if (!puKeyboard(k, PU_DOWN)) {
- if (default_input != 0)
- default_input->doKey(k, get_mods(), x, y);
- }
-}
-
-void
-GLUTkeyup(unsigned char k, int x, int y)
-{
- if (default_input != 0)
- default_input->doKey(k, get_mods()|FGInput::FG_MOD_UP, x, y);
-}
-
-void
-GLUTspecialkey(int k, int x, int y)
-{
- // Give PUI a chance to grab it first.
- if (!puKeyboard(k + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN)) {
- if (default_input != 0)
- default_input->doKey(k + 256, get_mods(), x, y);
- }
-}
+ if((keymod & KEYMOD_RELEASED) == 0)
+ if(puKeyboard(key, PU_DOWN))
+ return;
-void
-GLUTspecialkeyup(int k, int x, int y)
-{
- if (default_input != 0)
- default_input->doKey(k + 256, get_mods()|FGInput::FG_MOD_UP, x, y);
+ if(default_input)
+ default_input->doKey(key, keymod, mousex, mousey);
}
-void
-GLUTmouse (int button, int updown, int x, int y)
+void mouseClickHandler(int button, int updown, int x, int y)
{
- if (default_input != 0)
+ if(default_input)
default_input->doMouseClick(button, updown, x, y);
}
-void
-GLUTmotion (int x, int y)
+void mouseMotionHandler(int x, int y)
{
if (default_input != 0)
default_input->doMouseMotion(x, y);
}
-
-// end of input.cxx
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
+#include <Main/fg_os.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
class FGInput : public SGSubsystem
{
public:
-
- enum {
- FG_MOD_NONE = 0,
- FG_MOD_UP = 1, // key- or button-up
- FG_MOD_SHIFT = 2,
- FG_MOD_CTRL = 4,
- FG_MOD_ALT = 8,
- FG_MOD_MAX = 16 // enough to handle all combinations
- };
-
-
/**
* Default constructor.
*/
FGInput ();
-
/**
* Destructor.
*/
/**
* Handle a single keystroke.
*
- * <p>Note: for special keys, the integer key code will be the Glut
- * code + 256.</p>
- *
- * @param k The integer key code, as returned by glut.
+ * @param k The integer key code, see Main/fg_os.hxx
* @param modifiers Modifier keys pressed (bitfield).
* @param x The mouse x position at the time of keypress.
* @param y The mouse y position at the time of keypress.
- * @see #FG_MOD_SHIFT
- * @see #FG_MOD_CTRL
- * @see #FG_MOD_ALT
*/
virtual void doKey (int k, int modifiers, int x, int y);
float interval_sec;
float last_dt;
int last_state;
- binding_list_t bindings[FG_MOD_MAX];
+ binding_list_t bindings[KEYMOD_MAX];
};
virtual ~axis ();
float last_value;
float tolerance;
- binding_list_t bindings[FG_MOD_MAX];
+ binding_list_t bindings[KEYMOD_MAX];
float low_threshold;
float high_threshold;
struct button low;
bool constrained;
bool pass_through;
button * buttons;
- binding_list_t x_bindings[FG_MOD_MAX];
- binding_list_t y_bindings[FG_MOD_MAX];
+ binding_list_t x_bindings[KEYMOD_MAX];
+ binding_list_t y_bindings[KEYMOD_MAX];
};
};
-
-\f
-////////////////////////////////////////////////////////////////////////
-// GLUT callbacks.
-////////////////////////////////////////////////////////////////////////
-
-// Handle GLUT events.
-extern "C" {
-
-/**
- * Key-down event handler for Glut.
- *
- * <p>Pass the value on to the FGInput module unless PUI wants it.</p>
- *
- * @param k The integer value for the key pressed.
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTkey (unsigned char k, int x, int y);
-
-
-/**
- * Key-up event handler for GLUT.
- *
- * <p>PUI doesn't use this, so always pass it to the input manager.</p>
- *
- * @param k The integer value for the key pressed.
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTkeyup (unsigned char k, int x, int y);
-
-
-/**
- * Special key-down handler for Glut.
- *
- * <p>Pass the value on to the FGInput module unless PUI wants it.
- * The key value will have 256 added to it.</p>
- *
- * @param k The integer value for the key pressed (will have 256 added
- * to it).
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTspecialkey (int k, int x, int y);
-
-
-/**
- * Special key-up handler for Glut.
- *
- * @param k The integer value for the key pressed (will have 256 added
- * to it).
- * @param x (unused)
- * @param y (unused)
- */
-void GLUTspecialkeyup (int k, int x, int y);
-
-
-/**
- * Mouse click handler for Glut.
- *
- * @param button The mouse button pressed.
- * @param updown Press or release flag.
- * @param x The x-location of the click.
- * @param y The y-location of the click.
- */
-void GLUTmouse (int button, int updown, int x, int y);
-
-
-/**
- * Mouse motion handler for Glut.
- *
- * @param x The new x-location of the mouse.
- * @param y The new y-location of the mouse.
- */
-void GLUTmotion (int x, int y);
-
-} // extern "C"
-
#endif // _INPUT_HXX
splash.cxx splash.hxx \
util.cxx util.hxx \
viewer.cxx viewer.hxx \
- viewmgr.cxx viewmgr.hxx
+ viewmgr.cxx viewmgr.hxx \
+ fg_os.cxx fg_os.hxx
fgfs_SOURCES = bootstrap.cxx
# include <float.h>
#endif
-#include FG_GLUT_H
+#include "fg_os.hxx"
#ifdef macintosh
# include <console.h> // -dw- for command line dialog
{
PSN psn;
- glutInit (&argc, argv);
+ fgOSInit (&argc, argv);
CPSGetCurrentProcess(&psn);
CPSSetProcessName(&psn, "FlightGear");
--- /dev/null
+// The mac puts this in a weird location (GLUT/glut.h), so the
+// configure script detects the location and defines it as a macro.
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+# include FG_GLUT_H
+#else
+# include <GL/glut.h>
+#endif
+
+#include <plib/pu.h>
+
+#include "fg_os.hxx"
+
+//
+// fg_os callback registration APIs
+// (These are not glut-specific)
+//
+
+static fgIdleHandler IdleHandler = 0;
+static fgDrawHandler DrawHandler = 0;
+static fgWindowResizeHandler WindowResizeHandler = 0;
+static fgKeyHandler KeyHandler = 0;
+static fgMouseClickHandler MouseClickHandler = 0;
+static fgMouseMotionHandler MouseMotionHandler = 0;
+
+void fgRegisterIdleHandler(fgIdleHandler func)
+{
+ IdleHandler = func;
+}
+
+void fgRegisterDrawHandler(fgDrawHandler func)
+{
+ DrawHandler = func;
+}
+
+void fgRegisterWindowResizeHandler(fgWindowResizeHandler func)
+{
+ WindowResizeHandler = func;
+}
+
+void fgRegisterKeyHandler(fgKeyHandler func)
+{
+ KeyHandler = func;
+}
+
+void fgRegisterMouseClickHandler(fgMouseClickHandler func)
+{
+ MouseClickHandler = func;
+}
+
+void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
+{
+ MouseMotionHandler = func;
+}
+
+//
+// Native glut callbacks.
+// These translate the glut event model into fg*Handler callbacks
+//
+
+static int GlutModifiers = 0;
+
+static void callKeyHandler(int k, int mods, int x, int y)
+{
+ int puiup = mods & KEYMOD_RELEASED ? PU_UP : PU_DOWN;
+ if(puKeyboard(k, puiup))
+ return;
+ if(KeyHandler) (*KeyHandler)(k, mods, x, y);
+}
+
+static void GLUTmotion (int x, int y)
+{
+ if(MouseMotionHandler) (*MouseMotionHandler)(x, y);
+}
+
+static void GLUTmouse (int button, int updown, int x, int y)
+{
+ GlutModifiers = glutGetModifiers();
+ if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y);
+}
+
+static void GLUTspecialkeyup(int k, int x, int y)
+{
+ GlutModifiers = glutGetModifiers();
+ callKeyHandler(256 + k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
+}
+
+static void GLUTspecialkey(int k, int x, int y)
+{
+ GlutModifiers = glutGetModifiers();
+ callKeyHandler(256 + k, fgGetKeyModifiers(), x, y);
+}
+
+static void GLUTkeyup(unsigned char k, int x, int y)
+{
+ GlutModifiers = glutGetModifiers();
+ callKeyHandler(k, fgGetKeyModifiers() | KEYMOD_RELEASED, x, y);
+}
+
+static void GLUTkey(unsigned char k, int x, int y)
+{
+ GlutModifiers = glutGetModifiers();
+ callKeyHandler(k, fgGetKeyModifiers(), x, y);
+}
+
+static void GLUTidle()
+{
+ if(IdleHandler) (*IdleHandler)();
+}
+
+static void GLUTdraw()
+{
+ if(DrawHandler) (*DrawHandler)();
+ glutSwapBuffers();
+}
+
+static void GLUTreshape(int w, int h)
+{
+ if(WindowResizeHandler) (*WindowResizeHandler)(w, h);
+}
+
+//
+// fg_os API definition
+//
+
+void fgOSInit(int* argc, char** argv)
+{
+ glutInit(argc, argv);
+}
+
+void fgOSFullScreen()
+{
+ glutFullScreen();
+}
+
+void fgOSMainLoop()
+{
+ glutMainLoop();
+}
+
+static int CurrentCursor = MOUSE_CURSOR_POINTER;
+
+int fgGetMouseCursor()
+{
+ return CurrentCursor;
+}
+
+void fgSetMouseCursor(int cursor)
+{
+ CurrentCursor = cursor;
+ if (cursor == MOUSE_CURSOR_NONE) cursor = GLUT_CURSOR_NONE;
+ else if(cursor == MOUSE_CURSOR_POINTER) cursor = GLUT_CURSOR_INHERIT;
+ else if(cursor == MOUSE_CURSOR_WAIT) cursor = GLUT_CURSOR_WAIT;
+ else if(cursor == MOUSE_CURSOR_CROSSHAIR) cursor = GLUT_CURSOR_CROSSHAIR;
+ else if(cursor == MOUSE_CURSOR_LEFTRIGHT) cursor = GLUT_CURSOR_LEFT_RIGHT;
+ // Otherwise, pass it through unchanged...
+ glutSetCursor(cursor);
+}
+
+void fgWarpMouse(int x, int y)
+{
+ glutWarpPointer(x, y);
+}
+
+int fgGetKeyModifiers()
+{
+ int result = 0;
+ if(GlutModifiers & GLUT_ACTIVE_SHIFT) result |= KEYMOD_SHIFT;
+ if(GlutModifiers & GLUT_ACTIVE_CTRL) result |= KEYMOD_CTRL;
+ if(GlutModifiers & GLUT_ACTIVE_ALT) result |= KEYMOD_ALT;
+ return result;
+}
+
+void fgRequestRedraw()
+{
+ glutPostRedisplay();
+}
+
+void fgOSOpenWindow(int w, int h, bool alpha)
+{
+ int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
+ if(alpha) mode |= GLUT_ALPHA;
+
+ glutInitDisplayMode(mode);
+ glutInitWindowSize(w, h);
+ glutCreateWindow("FlightGear");
+
+ // Register these here. Calling them before the window is open
+ // crashes.
+ glutMotionFunc(GLUTmotion);
+ glutPassiveMotionFunc(GLUTmotion);
+ glutMouseFunc(GLUTmouse);
+ glutSpecialUpFunc(GLUTspecialkeyup);
+ glutSpecialFunc(GLUTspecialkey);
+ glutKeyboardUpFunc(GLUTkeyup);
+ glutKeyboardFunc(GLUTkey);
+ glutIdleFunc(GLUTidle);
+ glutDisplayFunc(GLUTdraw);
+ glutReshapeFunc(GLUTreshape);
+}
--- /dev/null
+#ifndef _FG_OS_HXX
+#define _FG_OS_HXX
+
+// Plib pui needs to know at compile time what toolkit is in use.
+// Change this when we move to something other than glut.
+#define PU_USE_GLUT
+
+enum { MOUSE_BUTTON_LEFT,
+ MOUSE_BUTTON_MIDDLE,
+ MOUSE_BUTTON_RIGHT };
+
+enum { MOUSE_BUTTON_DOWN,
+ MOUSE_BUTTON_UP };
+
+enum { MOUSE_CURSOR_NONE,
+ MOUSE_CURSOR_POINTER,
+ MOUSE_CURSOR_WAIT,
+ MOUSE_CURSOR_CROSSHAIR,
+ MOUSE_CURSOR_LEFTRIGHT };
+
+enum { KEYMOD_NONE = 0,
+ KEYMOD_RELEASED = 1, // Not a mod key, indicates "up" action
+ KEYMOD_SHIFT = 2,
+ KEYMOD_CTRL = 4,
+ KEYMOD_ALT = 8,
+ KEYMOD_MAX = 16 };
+
+// A note on key codes: none are defined here. FlightGear has no
+// hard-coded interpretations of codes other than modifier keys, so we
+// can get away with that. The only firm requirement is that the
+// codes passed to the fgKeyHandler function be correctly interpreted
+// by the PUI library. Users who need to hard-code key codes
+// (probably not a good idea in any case) can use the pu.hxx header
+// for definitions.
+
+//
+// OS integration functions
+//
+
+void fgOSInit(int* argc, char** argv);
+void fgOSOpenWindow(int w, int h, bool alpha);
+void fgOSFullScreen();
+void fgOSMainLoop();
+
+void fgSetMouseCursor(int cursor);
+int fgGetMouseCursor();
+void fgWarpMouse(int x, int y);
+
+int fgGetKeyModifiers();
+
+void fgRequestRedraw();
+
+//
+// Callbacks and registration API
+//
+
+typedef void (*fgIdleHandler)();
+typedef void (*fgDrawHandler)();
+typedef void (*fgWindowResizeHandler)(int w, int h);
+
+typedef void (*fgKeyHandler)(int key, int keymod, int mousex, int mousey);
+typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y);
+typedef void (*fgMouseMotionHandler)(int x, int y);
+
+void fgRegisterIdleHandler(fgIdleHandler func);
+void fgRegisterDrawHandler(fgDrawHandler func);
+void fgRegisterWindowResizeHandler(fgWindowResizeHandler func);
+
+void fgRegisterKeyHandler(fgKeyHandler func);
+void fgRegisterMouseClickHandler(fgMouseClickHandler func);
+void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
+
+#endif // _FG_OS_HXX
#endif
#include <plib/ssg.h>
-#include <plib/pu.h>
#include <plib/netSocket.h>
#include <simgear/screen/extensions.hxx>
FGGeneral general;
// Specify our current idle function state. This is used to run all
-// our initializations out of the glutIdleLoop() so that we can get a
+// our initializations out of the idle callback so that we can get a
// splash screen up and running right away.
static int idle_state = 0;
static long global_multi_loop;
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
-// The following defines flightgear options. Because glutlib will also
-// want to parse its own options, those options must not be included here
-// or they will get parsed by the main program option parser. Hence case
-// is significant for any option added that might be in conflict with
-// glutlib's parser.
-//
-// glutlib parses for:
-// -display
-// -direct (invalid in Win32)
-// -geometry
-// -gldebug
-// -iconized
-// -indirect (invalid in Win32)
-// -synce
-//
-// Note that glutlib depends upon strings while this program's
-// option parser wants only initial characters followed by numbers
-// or pathnames.
-//
-
-
ssgSimpleState *cloud3d_imposter_state;
ssgSimpleState *default_state;
ssgSimpleState *hud_and_panel;
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
-#ifndef GLUT_WRONG_VERSION
// Go full screen if requested ...
if ( fgGetBool("/sim/startup/fullscreen") ) {
- glutFullScreen();
+ fgOSFullScreen();
}
-#endif
// If enabled, normal vectors specified with glNormal are scaled
// to unit length after transformation. Enabling this has
fgSplashUpdate(0.0, (3.0 - t) / 2.0);
}
}
-
- glutSwapBuffers();
}
// {
// fgJoystickRead();
// }
-#elif defined( ENABLE_GLUT_JOYSTICK )
- // Glut joystick support works by feeding a joystick handler
- // function to glut. This is taken care of once in the joystick
- // init routine and we don't have to worry about it again.
#endif
// Fix elevation. I'm just sticking this here for now, it should
// glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}
- // redraw display
- fgRenderFrame();
+ fgRequestRedraw();
SG_LOG( SG_ALL, SG_DEBUG, "" );
}
// We've finished all our initialization steps, from now on we
// run the main loop.
- glutIdleFunc(fgMainLoop);
+ fgRegisterIdleHandler(fgMainLoop);
} else {
if ( fgGetBool("/sim/startup/splash-screen") ) {
fgSplashUpdate(0.0, 1.0);
}
-// Initialize GLUT and define a main window
-static bool fgGlutInit( int *argc, char **argv ) {
-
-#if !defined( macintosh )
- // GLUT will extract all glut specific options so later on we only
- // need wory about our own.
- glutInit(argc, argv);
-#endif
-
- // Define Display Parameters. Clouds3d works best with --bpp32 option
- if ( fgGetBool("/sim/rendering/clouds3d") ) {
- glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_ALPHA );
- } else {
- glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
- }
-
- SG_LOG( SG_GENERAL, SG_INFO, "Opening a window: " <<
- fgGetInt("/sim/startup/xsize") << "x"
- << fgGetInt("/sim/startup/ysize") );
-
- // Define initial window size
- glutInitWindowSize( fgGetInt("/sim/startup/xsize"),
- fgGetInt("/sim/startup/ysize") );
-
- // Initialize windows
- if ( !fgGetBool("/sim/startup/game-mode")) {
- // Open the regular window
- glutCreateWindow("FlightGear");
-#ifndef GLUT_WRONG_VERSION
- } else {
- // Open the cool new 'game mode' window
- char game_mode_str[256];
-//#define SYNC_OPENGL_WITH_DESKTOP_SETTINGS
-#if defined(WIN32) && defined(SYNC_OPENGL_WITH_DESKTOP_SETTINGS)
-#ifndef ENUM_CURRENT_SETTINGS
-#define ENUM_CURRENT_SETTINGS ((DWORD)-1)
-#define ENUM_REGISTRY_SETTINGS ((DWORD)-2)
-#endif
-
- DEVMODE dm;
- dm.dmSize = sizeof(DEVMODE);
- EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
- fgSetInt("/sim/startup/xsize", dm.dmPelsWidth);
- fgSetInt("/sim/startup/ysize", dm.dmPelsHeight);
- glutInitWindowSize( fgGetInt("/sim/startup/xsize"),
- fgGetInt("/sim/startup/ysize") );
- sprintf( game_mode_str, "%dx%d:%d@%d",
- dm.dmPelsWidth,
- dm.dmPelsHeight,
- dm.dmBitsPerPel,
- dm.dmDisplayFrequency );
-#else
- // Open the cool new 'game mode' window
- sprintf( game_mode_str, "width=%d height=%d bpp=%d",
- fgGetInt("/sim/startup/xsize"),
- fgGetInt("/sim/startup/ysize"),
- fgGetInt("/sim/rendering/bits-per-pixel"));
-
-#endif // HAVE_WINDOWS_H
- SG_LOG( SG_GENERAL, SG_INFO,
- "game mode params = " << game_mode_str );
- glutGameModeString( game_mode_str );
- glutEnterGameMode();
-#endif // GLUT_WRONG_VERSION
- }
-
- // This seems to be the absolute earliest in the init sequence
- // that these calls will return valid info. Too bad it's after
- // we've already created and sized out window. :-(
- general.set_glVendor( (char *)glGetString ( GL_VENDOR ) );
- general.set_glRenderer( (char *)glGetString ( GL_RENDERER ) );
- general.set_glVersion( (char *)glGetString ( GL_VERSION ) );
- SG_LOG( SG_GENERAL, SG_INFO, general.get_glRenderer() );
-
- GLint tmp;
- glGetIntegerv( GL_MAX_TEXTURE_SIZE, &tmp );
- general.set_glMaxTexSize( tmp );
- SG_LOG ( SG_GENERAL, SG_INFO, "Max texture size = " << tmp );
-
- glGetIntegerv( GL_DEPTH_BITS, &tmp );
- general.set_glDepthBits( tmp );
- SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp );
-
- return true;
-}
-
-
-// Initialize GLUT event handlers
-static bool fgGlutInitEvents( void ) {
- // call fgReshape() on window resizes
- glutReshapeFunc( fgReshape );
-
- // keyboard and mouse callbacks are set in FGInput::init
-
- // call fgMainLoop() whenever there is
- // nothing else to do
- glutIdleFunc( fgIdleFunction );
-
- // draw the scene
- glutDisplayFunc( fgRenderFrame );
-
- return true;
-}
-
// Main top level initialization
bool fgMainInit( int argc, char **argv ) {
}
// Initialize the Window/Graphics environment.
- if( !fgGlutInit(&argc, argv) ) {
- SG_LOG( SG_GENERAL, SG_ALERT, "GLUT initialization failed ..." );
- exit(-1);
- }
+#if !defined(__APPLE__) || defined(OSX_BUNDLE)
+ // Mac OS X command line ("non-bundle") applications call this
+ // from main(), in bootstrap.cxx. Andy doesn't know why, someone
+ // feel free to add comments...
+ fgOSInit(&argc, argv);
+#endif
- // Initialize the various GLUT Event Handlers.
- if( !fgGlutInitEvents() ) {
- SG_LOG( SG_GENERAL, SG_ALERT,
- "GLUT event handler initialization failed ..." );
- exit(-1);
- }
+ fgRegisterWindowResizeHandler( fgReshape );
+ fgRegisterIdleHandler( fgIdleFunction );
+ fgRegisterDrawHandler( fgRenderFrame );
+
+ // Clouds3D requires an alpha channel
+ fgOSOpenWindow( fgGetInt("/sim/startup/xsize"),
+ fgGetInt("/sim/startup/ysize"),
+ fgGetBool("/sim/rendering/clouds3d") );
+
+ // This seems to be the absolute earliest in the init sequence
+ // that these calls will return valid info. Too bad it's after
+ // we've already created and sized out window. :-(
+ general.set_glVendor( (char *)glGetString ( GL_VENDOR ) );
+ general.set_glRenderer( (char *)glGetString ( GL_RENDERER ) );
+ general.set_glVersion( (char *)glGetString ( GL_VERSION ) );
+ SG_LOG( SG_GENERAL, SG_INFO, general.get_glRenderer() );
+
+ GLint tmp;
+ glGetIntegerv( GL_MAX_TEXTURE_SIZE, &tmp );
+ general.set_glMaxTexSize( tmp );
+ SG_LOG ( SG_GENERAL, SG_INFO, "Max texture size = " << tmp );
+
+ glGetIntegerv( GL_DEPTH_BITS, &tmp );
+ general.set_glDepthBits( tmp );
+ SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp );
// Initialize plib net interface
netInit( &argc, argv );
// Initialize ssg (from plib). Needs to come before we do any
- // other ssg stuff, but after opengl/glut has been initialized.
+ // other ssg stuff, but after opengl has been initialized.
ssgInit();
// Initialize the user interface (we need to do this before
- // passing off control to glut and before fgInitGeneral to get our
- // fonts !!!
+ // passing off control to the OS main loop and before
+ // fgInitGeneral to get our fonts !!!
guiInit();
// Read the list of available aircrafts
// build our custom render states
fgBuildRenderStates();
- // pass control off to the master GLUT event handler
- glutMainLoop();
+ // pass control off to the master event handler
+ fgOSMainLoop();
// we never actually get here ... but to avoid compiler warnings,
// etc.
# include <windows.h>
#endif
-#include FG_GLUT_H
-
#include <string.h>
+#include <GL/glu.h>
+
#include <simgear/debug/logstream.hxx>
#include <simgear/screen/texture.hxx>
#include <simgear/math/sg_random.h>
#include "globals.hxx"
#include "fg_props.hxx"
#include "splash.hxx"
+#include "fg_os.hxx"
+
static SGTexture splash;
glTexCoord2f(0.0, 1.0); glVertex2f(xmin, ymax);
glEnd();
- glutSwapBuffers();
-
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);