Moved joystick initialization to happen *after* the construction of windows, to fix a deadlock happening on Windows at DLL loading

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1003 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-01-30 14:12:56 +00:00
parent 2f524481c1
commit c3687b4018
3 changed files with 274 additions and 259 deletions

View File

@ -43,8 +43,8 @@ myWindow (NULL),
myLastFrameTime (0.f), myLastFrameTime (0.f),
myIsExternal (false), myIsExternal (false),
myFramerateLimit(0), myFramerateLimit(0),
mySetCursorPosX (-1), mySetCursorPosX (0xFFFF),
mySetCursorPosY (-1) mySetCursorPosY (0xFFFF)
{ {
} }
@ -73,8 +73,8 @@ myWindow (NULL),
myLastFrameTime (0.f), myLastFrameTime (0.f),
myIsExternal (true), myIsExternal (true),
myFramerateLimit(0), myFramerateLimit(0),
mySetCursorPosX (-1), mySetCursorPosX (0xFFFF),
mySetCursorPosY (-1) mySetCursorPosY (0xFFFF)
{ {
Create(Handle, Params); Create(Handle, Params);
} }
@ -413,11 +413,12 @@ void Window::OnEvent(const Event& EventReceived)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Window::Initialize(priv::WindowImpl* Window) void Window::Initialize(priv::WindowImpl* Window)
{ {
// Assign new window and listen to its events // Assign and initialize the new window
myWindow = Window; myWindow = Window;
myWindow->AddListener(this); myWindow->Initialize();
// Attach input to the window // Listen to events from the new window
myWindow->AddListener(this);
myWindow->AddListener(&myInput); myWindow->AddListener(&myInput);
// Setup default behaviours (to get a consistent behaviour across different implementations) // Setup default behaviours (to get a consistent behaviour across different implementations)

View File

@ -1,252 +1,260 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// SFML - Simple and Fast Multimedia Library // SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) // Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
// //
// This software is provided 'as-is', without any express or implied warranty. // This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software. // In no event will the authors be held liable for any damages arising from the use of this software.
// //
// Permission is granted to anyone to use this software for any purpose, // Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely, // including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions: // subject to the following restrictions:
// //
// 1. The origin of this software must not be misrepresented; // 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software. // you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment // If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required. // in the product documentation would be appreciated but is not required.
// //
// 2. Altered source versions must be plainly marked as such, // 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software. // and must not be misrepresented as being the original software.
// //
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowListener.hpp> #include <SFML/Window/WindowListener.hpp>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#if defined(SFML_SYSTEM_WINDOWS) #if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/WindowImplWin32.hpp> #include <SFML/Window/Win32/WindowImplWin32.hpp>
typedef sf::priv::WindowImplWin32 WindowImplType; typedef sf::priv::WindowImplWin32 WindowImplType;
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD) #elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
#include <SFML/Window/Linux/WindowImplX11.hpp> #include <SFML/Window/Linux/WindowImplX11.hpp>
typedef sf::priv::WindowImplX11 WindowImplType; typedef sf::priv::WindowImplX11 WindowImplType;
#elif defined(SFML_SYSTEM_MACOS) #elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/Cocoa/WindowImplCocoa.hpp> #include <SFML/Window/Cocoa/WindowImplCocoa.hpp>
typedef sf::priv::WindowImplCocoa WindowImplType; typedef sf::priv::WindowImplCocoa WindowImplType;
#endif #endif
namespace sf namespace sf
{ {
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create a new window depending on the current OS /// Create a new window depending on the current OS
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl* WindowImpl::New() WindowImpl* WindowImpl::New()
{ {
return new WindowImplType(); return new WindowImplType();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create a new window depending on the current OS /// Create a new window depending on the current OS
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl* WindowImpl::New(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) WindowImpl* WindowImpl::New(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params)
{ {
return new WindowImplType(Mode, Title, WindowStyle, Params); return new WindowImplType(Mode, Title, WindowStyle, Params);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create a new window depending on the current OS /// Create a new window depending on the current OS
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl* WindowImpl::New(WindowHandle Handle, WindowSettings& Params) WindowImpl* WindowImpl::New(WindowHandle Handle, WindowSettings& Params)
{ {
return new WindowImplType(Handle, Params); return new WindowImplType(Handle, Params);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Default constructor /// Default constructor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl::WindowImpl() : WindowImpl::WindowImpl() :
myWidth (0), myWidth (0),
myHeight (0), myHeight (0),
myJoyThreshold(0.1f) myJoyThreshold(0.1f)
{ {
// Initialize the joysticks }
for (unsigned int i = 0; i < JoysticksCount; ++i)
{
myJoysticks[i].Initialize(i); ////////////////////////////////////////////////////////////
myJoyStates[i] = myJoysticks[i].UpdateState(); /// Destructor
} ////////////////////////////////////////////////////////////
} WindowImpl::~WindowImpl()
{
// Nothing to do
//////////////////////////////////////////////////////////// }
/// Destructor
////////////////////////////////////////////////////////////
WindowImpl::~WindowImpl() ////////////////////////////////////////////////////////////
{ /// Add a listener to the window
// Nothing to do ////////////////////////////////////////////////////////////
} void WindowImpl::AddListener(WindowListener* Listener)
{
if (Listener)
//////////////////////////////////////////////////////////// myListeners.insert(Listener);
/// Add a listener to the window }
////////////////////////////////////////////////////////////
void WindowImpl::AddListener(WindowListener* Listener)
{ ////////////////////////////////////////////////////////////
if (Listener) /// Remove a listener from the window
myListeners.insert(Listener); ////////////////////////////////////////////////////////////
} void WindowImpl::RemoveListener(WindowListener* Listener)
{
myListeners.erase(Listener);
//////////////////////////////////////////////////////////// }
/// Remove a listener from the window
////////////////////////////////////////////////////////////
void WindowImpl::RemoveListener(WindowListener* Listener) ////////////////////////////////////////////////////////////
{ /// Initialize window's states that can't be done at construction
myListeners.erase(Listener); ////////////////////////////////////////////////////////////
} void WindowImpl::Initialize()
{
// Initialize the joysticks
//////////////////////////////////////////////////////////// for (unsigned int i = 0; i < JoysticksCount; ++i)
/// Get the client width of the window {
//////////////////////////////////////////////////////////// myJoysticks[i].Initialize(i);
unsigned int WindowImpl::GetWidth() const myJoyStates[i] = myJoysticks[i].UpdateState();
{ }
return myWidth; }
}
////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// /// Get the client width of the window
/// Get the client height of the window ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// unsigned int WindowImpl::GetWidth() const
unsigned int WindowImpl::GetHeight() const {
{ return myWidth;
return myHeight; }
}
////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// /// Get the client height of the window
/// Change the joystick threshold, ie. the value below which ////////////////////////////////////////////////////////////
/// no move event will be generated unsigned int WindowImpl::GetHeight() const
//////////////////////////////////////////////////////////// {
void WindowImpl::SetJoystickThreshold(float Threshold) return myHeight;
{ }
myJoyThreshold = Threshold;
}
////////////////////////////////////////////////////////////
/// Change the joystick threshold, ie. the value below which
//////////////////////////////////////////////////////////// /// no move event will be generated
/// Process incoming events from operating system ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// void WindowImpl::SetJoystickThreshold(float Threshold)
void WindowImpl::DoEvents() {
{ myJoyThreshold = Threshold;
// Read the joysticks state and generate the appropriate events }
ProcessJoystickEvents();
// Let the derived class process other events ////////////////////////////////////////////////////////////
ProcessEvents(); /// Process incoming events from operating system
} ////////////////////////////////////////////////////////////
void WindowImpl::DoEvents()
{
//////////////////////////////////////////////////////////// // Read the joysticks state and generate the appropriate events
/// Check if there's an active context on the current thread ProcessJoystickEvents();
////////////////////////////////////////////////////////////
bool WindowImpl::IsContextActive() // Let the derived class process other events
{ ProcessEvents();
return WindowImplType::IsContextActive(); }
}
////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// /// Check if there's an active context on the current thread
/// Send an event to listeners ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// bool WindowImpl::IsContextActive()
void WindowImpl::SendEvent(const Event& EventToSend) {
{ return WindowImplType::IsContextActive();
for (std::set<WindowListener*>::iterator i = myListeners.begin(); i != myListeners.end(); ++i) }
{
(*i)->OnEvent(EventToSend);
} ////////////////////////////////////////////////////////////
} /// Send an event to listeners
////////////////////////////////////////////////////////////
void WindowImpl::SendEvent(const Event& EventToSend)
//////////////////////////////////////////////////////////// {
/// Evaluate a pixel format configuration. for (std::set<WindowListener*>::iterator i = myListeners.begin(); i != myListeners.end(); ++i)
/// This functions can be used by implementations that have {
/// several valid formats and want to get the best one (*i)->OnEvent(EventToSend);
//////////////////////////////////////////////////////////// }
int WindowImpl::EvaluateConfig(const VideoMode& Mode, const WindowSettings& Settings, int ColorBits, int DepthBits, int StencilBits, int Antialiasing) }
{
return abs(static_cast<int>(Mode.BitsPerPixel - ColorBits)) +
abs(static_cast<int>(Settings.DepthBits - DepthBits)) + ////////////////////////////////////////////////////////////
abs(static_cast<int>(Settings.StencilBits - StencilBits)) + /// Evaluate a pixel format configuration.
abs(static_cast<int>(Settings.AntialiasingLevel - Antialiasing)); /// This functions can be used by implementations that have
} /// several valid formats and want to get the best one
////////////////////////////////////////////////////////////
int WindowImpl::EvaluateConfig(const VideoMode& Mode, const WindowSettings& Settings, int ColorBits, int DepthBits, int StencilBits, int Antialiasing)
//////////////////////////////////////////////////////////// {
/// Read the joysticks state and generate the appropriate events return abs(static_cast<int>(Mode.BitsPerPixel - ColorBits)) +
//////////////////////////////////////////////////////////// abs(static_cast<int>(Settings.DepthBits - DepthBits)) +
void WindowImpl::ProcessJoystickEvents() abs(static_cast<int>(Settings.StencilBits - StencilBits)) +
{ abs(static_cast<int>(Settings.AntialiasingLevel - Antialiasing));
for (unsigned int i = 0; i < JoysticksCount; ++i) }
{
// Copy the previous state of the joystick and get the new one
JoystickState PreviousState = myJoyStates[i]; ////////////////////////////////////////////////////////////
myJoyStates[i] = myJoysticks[i].UpdateState(); /// Read the joysticks state and generate the appropriate events
////////////////////////////////////////////////////////////
// Axis void WindowImpl::ProcessJoystickEvents()
for (unsigned int j = 0; j < myJoysticks[i].GetAxesCount(); ++j) {
{ for (unsigned int i = 0; i < JoysticksCount; ++i)
float PrevPos = PreviousState.Axis[j]; {
float CurrPos = myJoyStates[i].Axis[j]; // Copy the previous state of the joystick and get the new one
if (fabs(CurrPos - PrevPos) >= myJoyThreshold) JoystickState PreviousState = myJoyStates[i];
{ myJoyStates[i] = myJoysticks[i].UpdateState();
Event Event;
Event.Type = Event::JoyMoved; // Axis
Event.JoyMove.JoystickId = i; for (unsigned int j = 0; j < myJoysticks[i].GetAxesCount(); ++j)
Event.JoyMove.Axis = static_cast<Joy::Axis>(j); {
Event.JoyMove.Position = CurrPos; float PrevPos = PreviousState.Axis[j];
SendEvent(Event); float CurrPos = myJoyStates[i].Axis[j];
} if (fabs(CurrPos - PrevPos) >= myJoyThreshold)
} {
Event Event;
// Buttons Event.Type = Event::JoyMoved;
for (unsigned int j = 0; j < myJoysticks[i].GetButtonsCount(); ++j) Event.JoyMove.JoystickId = i;
{ Event.JoyMove.Axis = static_cast<Joy::Axis>(j);
bool PrevPressed = PreviousState.Buttons[j]; Event.JoyMove.Position = CurrPos;
bool CurrPressed = myJoyStates[i].Buttons[j]; SendEvent(Event);
}
if ((!PrevPressed && CurrPressed) || (PrevPressed && !CurrPressed)) }
{
Event Event; // Buttons
Event.Type = CurrPressed ? Event::JoyButtonPressed : Event::JoyButtonReleased; for (unsigned int j = 0; j < myJoysticks[i].GetButtonsCount(); ++j)
Event.JoyButton.JoystickId = i; {
Event.JoyButton.Button = j; bool PrevPressed = PreviousState.Buttons[j];
SendEvent(Event); bool CurrPressed = myJoyStates[i].Buttons[j];
}
} if ((!PrevPressed && CurrPressed) || (PrevPressed && !CurrPressed))
} {
} Event Event;
Event.Type = CurrPressed ? Event::JoyButtonPressed : Event::JoyButtonReleased;
Event.JoyButton.JoystickId = i;
} // namespace priv Event.JoyButton.Button = j;
SendEvent(Event);
} // namespace sf }
}
}
}
} // namespace priv
} // namespace sf

View File

@ -108,6 +108,12 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RemoveListener(WindowListener* Listener); void RemoveListener(WindowListener* Listener);
////////////////////////////////////////////////////////////
/// Initialize window's states that can't be done at construction
///
////////////////////////////////////////////////////////////
void Initialize();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Get the client width of the window /// Get the client width of the window
/// ///