diff options
Diffstat (limited to 'src/SFML/Window/Win32')
-rw-r--r-- | src/SFML/Window/Win32/InputImpl.cpp | 35 | ||||
-rw-r--r-- | src/SFML/Window/Win32/InputImpl.hpp | 49 | ||||
-rw-r--r-- | src/SFML/Window/Win32/JoystickImpl.cpp | 491 | ||||
-rw-r--r-- | src/SFML/Window/Win32/JoystickImpl.hpp | 260 | ||||
-rw-r--r-- | src/SFML/Window/Win32/SensorImpl.cpp | 88 | ||||
-rw-r--r-- | src/SFML/Window/Win32/SensorImpl.hpp | 101 | ||||
-rw-r--r-- | src/SFML/Window/Win32/VideoModeImpl.cpp | 142 | ||||
-rw-r--r-- | src/SFML/Window/Win32/WglContext.cpp | 650 | ||||
-rw-r--r-- | src/SFML/Window/Win32/WglContext.hpp | 272 | ||||
-rw-r--r-- | src/SFML/Window/Win32/WindowImplWin32.cpp | 1964 | ||||
-rw-r--r-- | src/SFML/Window/Win32/WindowImplWin32.hpp | 509 |
11 files changed, 2524 insertions, 2037 deletions
diff --git a/src/SFML/Window/Win32/InputImpl.cpp b/src/SFML/Window/Win32/InputImpl.cpp index 0ad303b..bace512 100644 --- a/src/SFML/Window/Win32/InputImpl.cpp +++ b/src/SFML/Window/Win32/InputImpl.cpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) // // 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. @@ -148,7 +148,7 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) case Keyboard::F12: vkey = VK_F12; break; case Keyboard::F13: vkey = VK_F13; break; case Keyboard::F14: vkey = VK_F14; break; - case Keyboard::F15: vkey = VK_F16; break; + case Keyboard::F15: vkey = VK_F15; break; case Keyboard::Pause: vkey = VK_PAUSE; break; } @@ -157,6 +157,13 @@ bool InputImpl::isKeyPressed(Keyboard::Key key) //////////////////////////////////////////////////////////// +void InputImpl::setVirtualKeyboardVisible(bool visible) +{ + // Not applicable +} + + +//////////////////////////////////////////////////////////// bool InputImpl::isMouseButtonPressed(Mouse::Button button) { int vkey = 0; @@ -220,6 +227,30 @@ void InputImpl::setMousePosition(const Vector2i& position, const Window& relativ } } + +//////////////////////////////////////////////////////////// +bool InputImpl::isTouchDown(unsigned int /*finger*/) +{ + // Not applicable + return false; +} + + +//////////////////////////////////////////////////////////// +Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/) +{ + // Not applicable + return Vector2i(); +} + + +//////////////////////////////////////////////////////////// +Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*relativeTo*/) +{ + // Not applicable + return Vector2i(); +} + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Win32/InputImpl.hpp b/src/SFML/Window/Win32/InputImpl.hpp index 0669b4a..f62f2d2 100644 --- a/src/SFML/Window/Win32/InputImpl.hpp +++ b/src/SFML/Window/Win32/InputImpl.hpp @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// // // SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) // // 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. @@ -42,7 +42,7 @@ namespace priv //////////////////////////////////////////////////////////// class InputImpl { -public : +public: //////////////////////////////////////////////////////////// /// \brief Check if a key is pressed @@ -55,6 +55,14 @@ public : static bool isKeyPressed(Keyboard::Key key); //////////////////////////////////////////////////////////// + /// \brief Show or hide the virtual keyboard + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + static void setVirtualKeyboardVisible(bool visible); + + //////////////////////////////////////////////////////////// /// \brief Check if a mouse button is pressed /// /// \param button Button to check @@ -113,6 +121,43 @@ public : /// //////////////////////////////////////////////////////////// static void setMousePosition(const Vector2i& position, const Window& relativeTo); + + //////////////////////////////////////////////////////////// + /// \brief Check if a touch event is currently down + /// + /// \param finger Finger index + /// + /// \return True if \a finger is currently touching the screen, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isTouchDown(unsigned int finger); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of a touch in desktop coordinates + /// + /// This function returns the current touch position + /// in global (desktop) coordinates. + /// + /// \param finger Finger index + /// + /// \return Current position of \a finger, or undefined if it's not down + /// + //////////////////////////////////////////////////////////// + static Vector2i getTouchPosition(unsigned int finger); + + //////////////////////////////////////////////////////////// + /// \brief Get the current position of a touch in window coordinates + /// + /// This function returns the current touch position + /// in global (desktop) coordinates. + /// + /// \param finger Finger index + /// \param relativeTo Reference window + /// + /// \return Current position of \a finger, or undefined if it's not down + /// + //////////////////////////////////////////////////////////// + static Vector2i getTouchPosition(unsigned int finger, const Window& relativeTo); }; } // namespace priv diff --git a/src/SFML/Window/Win32/JoystickImpl.cpp b/src/SFML/Window/Win32/JoystickImpl.cpp index c2645e8..380e25f 100644 --- a/src/SFML/Window/Win32/JoystickImpl.cpp +++ b/src/SFML/Window/Win32/JoystickImpl.cpp @@ -1,189 +1,302 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/JoystickImpl.hpp>
-#include <SFML/System/Clock.hpp>
-#include <windows.h>
-#include <cmath>
-
-
-namespace
-{
- struct ConnectionCache
- {
- ConnectionCache() : connected(false) {}
- bool connected;
- sf::Clock timer;
- };
-
- const sf::Time connectionRefreshDelay = sf::milliseconds(500);
- ConnectionCache connectionCache[sf::Joystick::Count];
-}
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-void JoystickImpl::initialize()
-{
- // Perform the initial scan and populate the connection cache
- for (unsigned int i = 0; i < Joystick::Count; ++i)
- {
- ConnectionCache& cache = connectionCache[i];
-
- // Check if the joystick is connected
- JOYINFOEX joyInfo;
- joyInfo.dwSize = sizeof(joyInfo);
- joyInfo.dwFlags = 0;
- cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR;
-
- // start the timeout
- cache.timer.restart();
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void JoystickImpl::cleanup()
-{
- // Nothing to do
-}
-
-
-////////////////////////////////////////////////////////////
-bool JoystickImpl::isConnected(unsigned int index)
-{
- // We check the connection state of joysticks only every N milliseconds,
- // because of a strange (buggy?) behaviour of joyGetPosEx when joysticks
- // are just plugged/unplugged -- it takes really long and kills the app performances
- ConnectionCache& cache = connectionCache[index];
- if (cache.timer.getElapsedTime() > connectionRefreshDelay)
- {
- cache.timer.restart();
-
- JOYINFOEX joyInfo;
- joyInfo.dwSize = sizeof(joyInfo);
- joyInfo.dwFlags = 0;
-
- cache.connected = joyGetPosEx(JOYSTICKID1 + index, &joyInfo) == JOYERR_NOERROR;
- return cache.connected;
- }
- else
- {
- return cache.connected;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-bool JoystickImpl::open(unsigned int index)
-{
- // No explicit "open" action is required
- m_index = JOYSTICKID1 + index;
-
- // Store the joystick capabilities
- return joyGetDevCaps(m_index, &m_caps, sizeof(m_caps)) == JOYERR_NOERROR;
-}
-
-
-////////////////////////////////////////////////////////////
-void JoystickImpl::close()
-{
- // Nothing to do
-}
-
-
-////////////////////////////////////////////////////////////
-JoystickCaps JoystickImpl::getCapabilities() const
-{
- JoystickCaps caps;
-
- caps.buttonCount = m_caps.wNumButtons;
- if (caps.buttonCount > Joystick::ButtonCount)
- caps.buttonCount = Joystick::ButtonCount;
-
- caps.axes[Joystick::X] = true;
- caps.axes[Joystick::Y] = true;
- caps.axes[Joystick::Z] = (m_caps.wCaps & JOYCAPS_HASZ) != 0;
- caps.axes[Joystick::R] = (m_caps.wCaps & JOYCAPS_HASR) != 0;
- caps.axes[Joystick::U] = (m_caps.wCaps & JOYCAPS_HASU) != 0;
- caps.axes[Joystick::V] = (m_caps.wCaps & JOYCAPS_HASV) != 0;
- caps.axes[Joystick::PovX] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0;
- caps.axes[Joystick::PovY] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0;
-
- return caps;
-}
-
-
-////////////////////////////////////////////////////////////
-JoystickState JoystickImpl::update()
-{
- JoystickState state;
-
- // Get the current joystick state
- JOYINFOEX pos;
- pos.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNBUTTONS;
- pos.dwFlags |= (m_caps.wCaps & JOYCAPS_POVCTS) ? JOY_RETURNPOVCTS : JOY_RETURNPOV;
- pos.dwSize = sizeof(JOYINFOEX);
- if (joyGetPosEx(m_index, &pos) == JOYERR_NOERROR)
- {
- // The joystick is connected
- state.connected = true;
-
- // Axes
- state.axes[Joystick::X] = (pos.dwXpos - (m_caps.wXmax + m_caps.wXmin) / 2.f) * 200.f / (m_caps.wXmax - m_caps.wXmin);
- state.axes[Joystick::Y] = (pos.dwYpos - (m_caps.wYmax + m_caps.wYmin) / 2.f) * 200.f / (m_caps.wYmax - m_caps.wYmin);
- state.axes[Joystick::Z] = (pos.dwZpos - (m_caps.wZmax + m_caps.wZmin) / 2.f) * 200.f / (m_caps.wZmax - m_caps.wZmin);
- state.axes[Joystick::R] = (pos.dwRpos - (m_caps.wRmax + m_caps.wRmin) / 2.f) * 200.f / (m_caps.wRmax - m_caps.wRmin);
- state.axes[Joystick::U] = (pos.dwUpos - (m_caps.wUmax + m_caps.wUmin) / 2.f) * 200.f / (m_caps.wUmax - m_caps.wUmin);
- state.axes[Joystick::V] = (pos.dwVpos - (m_caps.wVmax + m_caps.wVmin) / 2.f) * 200.f / (m_caps.wVmax - m_caps.wVmin);
-
- // Special case for POV, it is given as an angle
- if (pos.dwPOV != 0xFFFF)
- {
- float angle = pos.dwPOV / 18000.f * 3.141592654f;
- state.axes[Joystick::PovX] = std::cos(angle) * 100;
- state.axes[Joystick::PovY] = std::sin(angle) * 100;
- }
- else
- {
- state.axes[Joystick::PovX] = 0;
- state.axes[Joystick::PovY] = 0;
- }
-
- // Buttons
- for (unsigned int i = 0; i < Joystick::ButtonCount; ++i)
- state.buttons[i] = (pos.dwButtons & (1 << i)) != 0;
- }
-
- return state;
-}
-
-} // namespace priv
-
-} // namespace sf
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/JoystickImpl.hpp> +#include <SFML/System/Clock.hpp> +#include <SFML/System/Err.hpp> +#include <windows.h> +#include <tchar.h> +#include <regstr.h> +#include <algorithm> +#include <cmath> +#include <sstream> +#include <string> + +namespace +{ + struct ConnectionCache + { + ConnectionCache() : connected(false) {} + bool connected; + sf::Clock timer; + }; + + const sf::Time connectionRefreshDelay = sf::milliseconds(500); + ConnectionCache connectionCache[sf::Joystick::Count]; + + // Get a system error string from an error code + std::string getErrorString(DWORD error) + { + PTCHAR buffer; + + if (FormatMessage(FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, reinterpret_cast<PTCHAR>(&buffer), 0, NULL) == 0) + return "Unknown error."; + + sf::String message = buffer; + LocalFree(buffer); + return message.toAnsiString(); + } + + // Get the joystick's name + sf::String getDeviceName(unsigned int index, JOYCAPS caps) + { + // Give the joystick a default name + sf::String joystickDescription = "Unknown Joystick"; + + LONG result; + HKEY rootKey; + HKEY currentKey; + std::basic_string<TCHAR> subkey; + + subkey = REGSTR_PATH_JOYCONFIG; + subkey += TEXT('\\'); + subkey += caps.szRegKey; + subkey += TEXT('\\'); + subkey += REGSTR_KEY_JOYCURR; + + rootKey = HKEY_CURRENT_USER; + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + rootKey = HKEY_LOCAL_MACHINE; + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to open registry for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + } + + std::basic_ostringstream<TCHAR> indexString; + indexString << index + 1; + + subkey = TEXT("Joystick"); + subkey += indexString.str(); + subkey += REGSTR_VAL_JOYOEMNAME; + + TCHAR keyData[256]; + DWORD keyDataSize = sizeof(keyData); + + result = RegQueryValueEx(currentKey, subkey.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(keyData), &keyDataSize); + RegCloseKey(currentKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to query registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + subkey = REGSTR_PATH_JOYOEM; + subkey += TEXT('\\'); + subkey.append(keyData, keyDataSize / sizeof(TCHAR)); + + result = RegOpenKeyEx(rootKey, subkey.c_str(), 0, KEY_READ, ¤tKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to open registry key for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + keyDataSize = sizeof(keyData); + + result = RegQueryValueEx(currentKey, REGSTR_VAL_JOYOEMNAME, NULL, NULL, reinterpret_cast<LPBYTE>(keyData), &keyDataSize); + RegCloseKey(currentKey); + + if (result != ERROR_SUCCESS) + { + sf::err() << "Unable to query name for joystick at index " << index << ": " << getErrorString(result) << std::endl; + return joystickDescription; + } + + keyData[255] = TEXT('\0'); // Ensure null terminator in case the data is too long. + joystickDescription = keyData; + + return joystickDescription; + } +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void JoystickImpl::initialize() +{ + // Perform the initial scan and populate the connection cache + for (unsigned int i = 0; i < Joystick::Count; ++i) + { + ConnectionCache& cache = connectionCache[i]; + + // Check if the joystick is connected + JOYINFOEX joyInfo; + joyInfo.dwSize = sizeof(joyInfo); + joyInfo.dwFlags = 0; + cache.connected = joyGetPosEx(JOYSTICKID1 + i, &joyInfo) == JOYERR_NOERROR; + + // start the timeout + cache.timer.restart(); + } +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::cleanup() +{ + // Nothing to do +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::isConnected(unsigned int index) +{ + // We check the connection state of joysticks only every N milliseconds, + // because of a strange (buggy?) behavior of joyGetPosEx when joysticks + // are just plugged/unplugged -- it takes really long and kills the app performances + ConnectionCache& cache = connectionCache[index]; + if (cache.timer.getElapsedTime() > connectionRefreshDelay) + { + cache.timer.restart(); + + JOYINFOEX joyInfo; + joyInfo.dwSize = sizeof(joyInfo); + joyInfo.dwFlags = 0; + + cache.connected = joyGetPosEx(JOYSTICKID1 + index, &joyInfo) == JOYERR_NOERROR; + return cache.connected; + } + else + { + return cache.connected; + } +} + + +//////////////////////////////////////////////////////////// +bool JoystickImpl::open(unsigned int index) +{ + // No explicit "open" action is required + m_index = JOYSTICKID1 + index; + + // Store the joystick capabilities + bool success = joyGetDevCaps(m_index, &m_caps, sizeof(m_caps)) == JOYERR_NOERROR; + + if (success) + { + m_identification.name = getDeviceName(m_index, m_caps); + m_identification.productId = m_caps.wPid; + m_identification.vendorId = m_caps.wMid; + } + + return success; +} + + +//////////////////////////////////////////////////////////// +void JoystickImpl::close() +{ + // Nothing to do +} + +//////////////////////////////////////////////////////////// +JoystickCaps JoystickImpl::getCapabilities() const +{ + JoystickCaps caps; + + caps.buttonCount = m_caps.wNumButtons; + if (caps.buttonCount > Joystick::ButtonCount) + caps.buttonCount = Joystick::ButtonCount; + + caps.axes[Joystick::X] = true; + caps.axes[Joystick::Y] = true; + caps.axes[Joystick::Z] = (m_caps.wCaps & JOYCAPS_HASZ) != 0; + caps.axes[Joystick::R] = (m_caps.wCaps & JOYCAPS_HASR) != 0; + caps.axes[Joystick::U] = (m_caps.wCaps & JOYCAPS_HASU) != 0; + caps.axes[Joystick::V] = (m_caps.wCaps & JOYCAPS_HASV) != 0; + caps.axes[Joystick::PovX] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + caps.axes[Joystick::PovY] = (m_caps.wCaps & JOYCAPS_HASPOV) != 0; + + return caps; +} + + +//////////////////////////////////////////////////////////// +Joystick::Identification JoystickImpl::getIdentification() const +{ + return m_identification; +} + + +//////////////////////////////////////////////////////////// +JoystickState JoystickImpl::update() +{ + JoystickState state; + + // Get the current joystick state + JOYINFOEX pos; + pos.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNBUTTONS; + pos.dwFlags |= (m_caps.wCaps & JOYCAPS_POVCTS) ? JOY_RETURNPOVCTS : JOY_RETURNPOV; + pos.dwSize = sizeof(JOYINFOEX); + if (joyGetPosEx(m_index, &pos) == JOYERR_NOERROR) + { + // The joystick is connected + state.connected = true; + + // Axes + state.axes[Joystick::X] = (pos.dwXpos - (m_caps.wXmax + m_caps.wXmin) / 2.f) * 200.f / (m_caps.wXmax - m_caps.wXmin); + state.axes[Joystick::Y] = (pos.dwYpos - (m_caps.wYmax + m_caps.wYmin) / 2.f) * 200.f / (m_caps.wYmax - m_caps.wYmin); + state.axes[Joystick::Z] = (pos.dwZpos - (m_caps.wZmax + m_caps.wZmin) / 2.f) * 200.f / (m_caps.wZmax - m_caps.wZmin); + state.axes[Joystick::R] = (pos.dwRpos - (m_caps.wRmax + m_caps.wRmin) / 2.f) * 200.f / (m_caps.wRmax - m_caps.wRmin); + state.axes[Joystick::U] = (pos.dwUpos - (m_caps.wUmax + m_caps.wUmin) / 2.f) * 200.f / (m_caps.wUmax - m_caps.wUmin); + state.axes[Joystick::V] = (pos.dwVpos - (m_caps.wVmax + m_caps.wVmin) / 2.f) * 200.f / (m_caps.wVmax - m_caps.wVmin); + + // Special case for POV, it is given as an angle + if (pos.dwPOV != 0xFFFF) + { + float angle = pos.dwPOV / 18000.f * 3.141592654f; + state.axes[Joystick::PovX] = std::sin(angle) * 100; + state.axes[Joystick::PovY] = std::cos(angle) * 100; + } + else + { + state.axes[Joystick::PovX] = 0; + state.axes[Joystick::PovY] = 0; + } + + // Buttons + for (unsigned int i = 0; i < Joystick::ButtonCount; ++i) + state.buttons[i] = (pos.dwButtons & (1 << i)) != 0; + } + + return state; +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/JoystickImpl.hpp b/src/SFML/Window/Win32/JoystickImpl.hpp index 1630f99..a5d258d 100644 --- a/src/SFML/Window/Win32/JoystickImpl.hpp +++ b/src/SFML/Window/Win32/JoystickImpl.hpp @@ -1,125 +1,135 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-#ifndef SFML_JOYSTICKIMPLWIN32_HPP
-#define SFML_JOYSTICKIMPLWIN32_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#ifdef _WIN32_WINDOWS
- #undef _WIN32_WINDOWS
-#endif
-#ifdef _WIN32_WINNT
- #undef _WIN32_WINNT
-#endif
-#define _WIN32_WINDOWS 0x0501
-#define _WIN32_WINNT 0x0501
-#include <SFML/Window/JoystickImpl.hpp>
-#include <windows.h>
-#include <mmsystem.h>
-#include <cmath>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief Windows implementation of joysticks
-///
-////////////////////////////////////////////////////////////
-class JoystickImpl
-{
-public :
-
- ////////////////////////////////////////////////////////////
- /// \brief Perform the global initialization of the joystick module
- ///
- ////////////////////////////////////////////////////////////
- static void initialize();
-
- ////////////////////////////////////////////////////////////
- /// \brief Perform the global cleanup of the joystick module
- ///
- ////////////////////////////////////////////////////////////
- static void cleanup();
-
- ////////////////////////////////////////////////////////////
- /// \brief Check if a joystick is currently connected
- ///
- /// \param index Index of the joystick to check
- ///
- /// \return True if the joystick is connected, false otherwise
- ///
- ////////////////////////////////////////////////////////////
- static bool isConnected(unsigned int index);
-
- ////////////////////////////////////////////////////////////
- /// \brief Open the joystick
- ///
- /// \param index Index assigned to the joystick
- ///
- /// \return True on success, false on failure
- ///
- ////////////////////////////////////////////////////////////
- bool open(unsigned int index);
-
- ////////////////////////////////////////////////////////////
- /// \brief Close the joystick
- ///
- ////////////////////////////////////////////////////////////
- void close();
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the joystick capabilities
- ///
- /// \return Joystick capabilities
- ///
- ////////////////////////////////////////////////////////////
- JoystickCaps getCapabilities() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Update the joystick and get its new state
- ///
- /// \return Joystick state
- ///
- ////////////////////////////////////////////////////////////
- JoystickState update();
-
-private :
-
- ////////////////////////////////////////////////////////////
- // Member data
- ////////////////////////////////////////////////////////////
- unsigned int m_index; ///< Index of the joystick
- JOYCAPS m_caps; ///< Joystick capabilities
-};
-
-} // namespace priv
-
-} // namespace sf
-
-
-#endif // SFML_JOYSTICKIMPLWIN32_HPP
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_JOYSTICKIMPLWIN32_HPP +#define SFML_JOYSTICKIMPLWIN32_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#ifdef _WIN32_WINDOWS + #undef _WIN32_WINDOWS +#endif +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINDOWS 0x0501 +#define _WIN32_WINNT 0x0501 +#include <SFML/Window/Joystick.hpp> +#include <SFML/Window/JoystickImpl.hpp> +#include <SFML/System/String.hpp> +#include <windows.h> +#include <mmsystem.h> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of joysticks +/// +//////////////////////////////////////////////////////////// +class JoystickImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Perform the global initialization of the joystick module + /// + //////////////////////////////////////////////////////////// + static void initialize(); + + //////////////////////////////////////////////////////////// + /// \brief Perform the global cleanup of the joystick module + /// + //////////////////////////////////////////////////////////// + static void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Check if a joystick is currently connected + /// + /// \param index Index of the joystick to check + /// + /// \return True if the joystick is connected, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isConnected(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Open the joystick + /// + /// \param index Index assigned to the joystick + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool open(unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Close the joystick + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Get the joystick capabilities + /// + /// \return Joystick capabilities + /// + //////////////////////////////////////////////////////////// + JoystickCaps getCapabilities() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the joystick identification + /// + /// \return Joystick identification + /// + //////////////////////////////////////////////////////////// + Joystick::Identification getIdentification() const; + + //////////////////////////////////////////////////////////// + /// \brief Update the joystick and get its new state + /// + /// \return Joystick state + /// + //////////////////////////////////////////////////////////// + JoystickState update(); + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + unsigned int m_index; ///< Index of the joystick + JOYCAPS m_caps; ///< Joystick capabilities + Joystick::Identification m_identification; ///< Joystick identification +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_JOYSTICKIMPLWIN32_HPP diff --git a/src/SFML/Window/Win32/SensorImpl.cpp b/src/SFML/Window/Win32/SensorImpl.cpp new file mode 100644 index 0000000..be5e439 --- /dev/null +++ b/src/SFML/Window/Win32/SensorImpl.cpp @@ -0,0 +1,88 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/SensorImpl.hpp> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +void SensorImpl::initialize() +{ + // To be implemented +} + + +//////////////////////////////////////////////////////////// +void SensorImpl::cleanup() +{ + // To be implemented +} + + +//////////////////////////////////////////////////////////// +bool SensorImpl::isAvailable(Sensor::Type /*sensor*/) +{ + // To be implemented + return false; +} + + +//////////////////////////////////////////////////////////// +bool SensorImpl::open(Sensor::Type /*sensor*/) +{ + // To be implemented + return false; +} + + +//////////////////////////////////////////////////////////// +void SensorImpl::close() +{ + // To be implemented +} + + +//////////////////////////////////////////////////////////// +Vector3f SensorImpl::update() +{ + // To be implemented + return Vector3f(0, 0, 0); +} + + +//////////////////////////////////////////////////////////// +void SensorImpl::setEnabled(bool /*enabled*/) +{ + // To be implemented +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/SensorImpl.hpp b/src/SFML/Window/Win32/SensorImpl.hpp new file mode 100644 index 0000000..e174fa2 --- /dev/null +++ b/src/SFML/Window/Win32/SensorImpl.hpp @@ -0,0 +1,101 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_SENSORIMPLWIN32_HPP +#define SFML_SENSORIMPLWIN32_HPP + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of sensors +/// +//////////////////////////////////////////////////////////// +class SensorImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Perform the global initialization of the sensor module + /// + //////////////////////////////////////////////////////////// + static void initialize(); + + //////////////////////////////////////////////////////////// + /// \brief Perform the global cleanup of the sensor module + /// + //////////////////////////////////////////////////////////// + static void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Check if a sensor is available + /// + /// \param sensor Sensor to check + /// + /// \return True if the sensor is available, false otherwise + /// + //////////////////////////////////////////////////////////// + static bool isAvailable(Sensor::Type sensor); + + //////////////////////////////////////////////////////////// + /// \brief Open the sensor + /// + /// \param sensor Type of the sensor + /// + /// \return True on success, false on failure + /// + //////////////////////////////////////////////////////////// + bool open(Sensor::Type sensor); + + //////////////////////////////////////////////////////////// + /// \brief Close the sensor + /// + //////////////////////////////////////////////////////////// + void close(); + + //////////////////////////////////////////////////////////// + /// \brief Update the sensor and get its new value + /// + /// \return Sensor value + /// + //////////////////////////////////////////////////////////// + Vector3f update(); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable the sensor + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + void setEnabled(bool enabled); +}; + +} // namespace priv + +} // namespace sf + + +#endif // SFML_SENSORIMPLWIN32_HPP diff --git a/src/SFML/Window/Win32/VideoModeImpl.cpp b/src/SFML/Window/Win32/VideoModeImpl.cpp index 11f04ab..b19588a 100644 --- a/src/SFML/Window/Win32/VideoModeImpl.cpp +++ b/src/SFML/Window/Win32/VideoModeImpl.cpp @@ -1,71 +1,71 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/VideoModeImpl.hpp>
-#include <windows.h>
-#include <algorithm>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
-{
- std::vector<VideoMode> modes;
-
- // Enumerate all available video modes for the primary display adapter
- DEVMODE win32Mode;
- win32Mode.dmSize = sizeof(win32Mode);
- for (int count = 0; EnumDisplaySettings(NULL, count, &win32Mode); ++count)
- {
- // Convert to sf::VideoMode
- VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel);
-
- // Add it only if it is not already in the array
- if (std::find(modes.begin(), modes.end(), mode) == modes.end())
- modes.push_back(mode);
- }
-
- return modes;
-}
-
-
-////////////////////////////////////////////////////////////
-VideoMode VideoModeImpl::getDesktopMode()
-{
- DEVMODE win32Mode;
- win32Mode.dmSize = sizeof(win32Mode);
- EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &win32Mode);
-
- return VideoMode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel);
-}
-
-} // namespace priv
-
-} // namespace sf
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/VideoModeImpl.hpp> +#include <windows.h> +#include <algorithm> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +std::vector<VideoMode> VideoModeImpl::getFullscreenModes() +{ + std::vector<VideoMode> modes; + + // Enumerate all available video modes for the primary display adapter + DEVMODE win32Mode; + win32Mode.dmSize = sizeof(win32Mode); + for (int count = 0; EnumDisplaySettings(NULL, count, &win32Mode); ++count) + { + // Convert to sf::VideoMode + VideoMode mode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); + + // Add it only if it is not already in the array + if (std::find(modes.begin(), modes.end(), mode) == modes.end()) + modes.push_back(mode); + } + + return modes; +} + + +//////////////////////////////////////////////////////////// +VideoMode VideoModeImpl::getDesktopMode() +{ + DEVMODE win32Mode; + win32Mode.dmSize = sizeof(win32Mode); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &win32Mode); + + return VideoMode(win32Mode.dmPelsWidth, win32Mode.dmPelsHeight, win32Mode.dmBitsPerPel); +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp index 7d9cc43..c6e7c33 100644 --- a/src/SFML/Window/Win32/WglContext.cpp +++ b/src/SFML/Window/Win32/WglContext.cpp @@ -1,325 +1,325 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/WindowImpl.hpp> // included first to avoid a warning about macro redefinition
-#include <SFML/Window/Win32/WglContext.hpp>
-#include <SFML/Window/glext/wglext.h>
-#include <SFML/System/Lock.hpp>
-#include <SFML/System/Mutex.hpp>
-#include <SFML/System/Err.hpp>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-WglContext::WglContext(WglContext* shared) :
-m_window (NULL),
-m_deviceContext(NULL),
-m_context (NULL),
-m_ownsWindow (true)
-{
- // Creating a dummy window is mandatory: we could create a memory DC but then
- // its pixel format wouldn't match the regular contexts' format, and thus
- // wglShareLists would always fail. Too bad...
-
- // Create a dummy window (disabled and hidden)
- m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
- ShowWindow(m_window, SW_HIDE);
- m_deviceContext = GetDC(m_window);
-
- // Create the context
- if (m_deviceContext)
- createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
-}
-
-
-////////////////////////////////////////////////////////////
-WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
-m_window (NULL),
-m_deviceContext(NULL),
-m_context (NULL),
-m_ownsWindow (false)
-{
- // Get the owner window and its device context
- m_window = owner->getSystemHandle();
- m_deviceContext = GetDC(m_window);
-
- // Create the context
- if (m_deviceContext)
- createContext(shared, bitsPerPixel, settings);
-}
-
-
-////////////////////////////////////////////////////////////
-WglContext::WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) :
-m_window (NULL),
-m_deviceContext(NULL),
-m_context (NULL),
-m_ownsWindow (true)
-{
- // The target of the context is a hidden window.
- // We can't create a memory DC (the resulting context wouldn't be compatible
- // with other contexts), and we don't add the extra complexity of P-Buffers;
- // we can still support them in the future if this solution is not good enough.
-
- // Create the hidden window
- m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, width, height, NULL, NULL, GetModuleHandle(NULL), NULL);
- ShowWindow(m_window, SW_HIDE);
- m_deviceContext = GetDC(m_window);
-
- // Create the context
- if (m_deviceContext)
- createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings);
-}
-
-
-////////////////////////////////////////////////////////////
-WglContext::~WglContext()
-{
- // Destroy the OpenGL context
- if (m_context)
- {
- if (wglGetCurrentContext() == m_context)
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(m_context);
- }
-
- // Destroy the device context
- if (m_deviceContext)
- ReleaseDC(m_window, m_deviceContext);
-
- // Destroy the window if we own it
- if (m_window && m_ownsWindow)
- DestroyWindow(m_window);
-}
-
-
-////////////////////////////////////////////////////////////
-bool WglContext::makeCurrent()
-{
- return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context);
-}
-
-
-////////////////////////////////////////////////////////////
-void WglContext::display()
-{
- if (m_deviceContext && m_context)
- SwapBuffers(m_deviceContext);
-}
-
-
-////////////////////////////////////////////////////////////
-void WglContext::setVerticalSyncEnabled(bool enabled)
-{
- PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT"));
- if (wglSwapIntervalEXT)
- wglSwapIntervalEXT(enabled ? 1 : 0);
-}
-
-
-////////////////////////////////////////////////////////////
-void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
-{
- // Save the creation settings
- m_settings = settings;
-
- // Let's find a suitable pixel format -- first try with antialiasing
- int bestFormat = 0;
- if (m_settings.antialiasingLevel > 0)
- {
- // Get the wglChoosePixelFormatARB function (it is an extension)
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
- if (wglChoosePixelFormatARB)
- {
- // Define the basic attributes we want for our window
- int intAttributes[] =
- {
- WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
- WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? GL_TRUE : GL_FALSE),
- WGL_SAMPLES_ARB, static_cast<int>(m_settings.antialiasingLevel),
- 0, 0
- };
-
- // Let's check how many formats are supporting our requirements
- int formats[128];
- UINT nbFormats;
- float floatAttributes[] = {0, 0};
- bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
- while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0)
- {
- // Decrease the antialiasing level until we find a valid one
- m_settings.antialiasingLevel--;
- intAttributes[11] = m_settings.antialiasingLevel;
- isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0;
- }
-
- // Get the best format among the returned ones
- if (isValid && (nbFormats > 0))
- {
- int bestScore = 0xFFFF;
- for (UINT i = 0; i < nbFormats; ++i)
- {
- // Get the current format's attributes
- PIXELFORMATDESCRIPTOR attributes;
- attributes.nSize = sizeof(attributes);
- attributes.nVersion = 1;
- DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes);
-
- // Evaluate the current configuration
- int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits;
- int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel);
-
- // Keep it if it's better than the current best
- if (score < bestScore)
- {
- bestScore = score;
- bestFormat = formats[i];
- }
- }
- }
- }
- else
- {
- // wglChoosePixelFormatARB not supported ; disabling antialiasing
- err() << "Antialiasing is not supported ; it will be disabled" << std::endl;
- m_settings.antialiasingLevel = 0;
- }
- }
-
- // Find a pixel format with no antialiasing, if not needed or not supported
- if (bestFormat == 0)
- {
- // Setup a pixel format descriptor from the rendering settings
- PIXELFORMATDESCRIPTOR descriptor;
- ZeroMemory(&descriptor, sizeof(descriptor));
- descriptor.nSize = sizeof(descriptor);
- descriptor.nVersion = 1;
- descriptor.iLayerType = PFD_MAIN_PLANE;
- descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- descriptor.iPixelType = PFD_TYPE_RGBA;
- descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel);
- descriptor.cDepthBits = static_cast<BYTE>(m_settings.depthBits);
- descriptor.cStencilBits = static_cast<BYTE>(m_settings.stencilBits);
- descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0;
-
- // Get the pixel format that best matches our requirements
- bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
- if (bestFormat == 0)
- {
- err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl;
- return;
- }
- }
-
- // Extract the depth and stencil bits from the chosen format
- PIXELFORMATDESCRIPTOR actualFormat;
- actualFormat.nSize = sizeof(actualFormat);
- actualFormat.nVersion = 1;
- DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat);
- m_settings.depthBits = actualFormat.cDepthBits;
- m_settings.stencilBits = actualFormat.cStencilBits;
-
- // Set the chosen pixel format
- if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat))
- {
- err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl;
- return;
- }
-
- // Get the context to share display lists with
- HGLRC sharedContext = shared ? shared->m_context : NULL;
-
- // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code)
- while (!m_context && (m_settings.majorVersion >= 3))
- {
- PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));
- if (wglCreateContextAttribsARB)
- {
- int attributes[] =
- {
- WGL_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
- WGL_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
- WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
- 0, 0
- };
- m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes);
- }
-
- // If we couldn't create the context, lower the version number and try again -- stop at 3.0
- // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
- if (!m_context)
- {
- if (m_settings.minorVersion > 0)
- {
- // If the minor version is not 0, we decrease it and try again
- m_settings.minorVersion--;
- }
- else
- {
- // If the minor version is 0, we decrease the major version
- m_settings.majorVersion--;
- m_settings.minorVersion = 9;
- }
- }
- }
-
- // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context
- if (!m_context)
- {
- // set the context version to 2.0 (arbitrary)
- m_settings.majorVersion = 2;
- m_settings.minorVersion = 0;
-
- m_context = wglCreateContext(m_deviceContext);
- if (!m_context)
- {
- err() << "Failed to create an OpenGL context for this window" << std::endl;
- return;
- }
-
- // Share this context with others
- if (sharedContext)
- {
- // wglShareLists doesn't seem to be thread-safe
- static Mutex mutex;
- Lock lock(mutex);
-
- if (!wglShareLists(sharedContext, m_context))
- err() << "Failed to share the OpenGL context" << std::endl;
- }
- }
-}
-
-} // namespace priv
-
-} // namespace sf
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/WindowImpl.hpp> // included first to avoid a warning about macro redefinition +#include <SFML/Window/Win32/WglContext.hpp> +#include <SFML/Window/glext/wglext.h> +#include <SFML/System/Lock.hpp> +#include <SFML/System/Mutex.hpp> +#include <SFML/System/Err.hpp> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (true) +{ + // Creating a dummy window is mandatory: we could create a memory DC but then + // its pixel format wouldn't match the regular contexts' format, and thus + // wglShareLists would always fail. Too bad... + + // Create a dummy window (disabled and hidden) + m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); + ShowWindow(m_window, SW_HIDE); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); +} + + +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (false) +{ + // Get the owner window and its device context + m_window = owner->getSystemHandle(); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +WglContext::WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : +m_window (NULL), +m_deviceContext(NULL), +m_context (NULL), +m_ownsWindow (true) +{ + // The target of the context is a hidden window. + // We can't create a memory DC (the resulting context wouldn't be compatible + // with other contexts), and we don't add the extra complexity of P-Buffers; + // we can still support them in the future if this solution is not good enough. + + // Create the hidden window + m_window = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, width, height, NULL, NULL, GetModuleHandle(NULL), NULL); + ShowWindow(m_window, SW_HIDE); + m_deviceContext = GetDC(m_window); + + // Create the context + if (m_deviceContext) + createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); +} + + +//////////////////////////////////////////////////////////// +WglContext::~WglContext() +{ + // Destroy the OpenGL context + if (m_context) + { + if (wglGetCurrentContext() == m_context) + wglMakeCurrent(NULL, NULL); + wglDeleteContext(m_context); + } + + // Destroy the device context + if (m_deviceContext) + ReleaseDC(m_window, m_deviceContext); + + // Destroy the window if we own it + if (m_window && m_ownsWindow) + DestroyWindow(m_window); +} + + +//////////////////////////////////////////////////////////// +bool WglContext::makeCurrent() +{ + return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context); +} + + +//////////////////////////////////////////////////////////// +void WglContext::display() +{ + if (m_deviceContext && m_context) + SwapBuffers(m_deviceContext); +} + + +//////////////////////////////////////////////////////////// +void WglContext::setVerticalSyncEnabled(bool enabled) +{ + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT")); + if (wglSwapIntervalEXT) + wglSwapIntervalEXT(enabled ? 1 : 0); +} + + +//////////////////////////////////////////////////////////// +void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) +{ + // Save the creation settings + m_settings = settings; + + // Let's find a suitable pixel format -- first try with antialiasing + int bestFormat = 0; + if (m_settings.antialiasingLevel > 0) + { + // Get the wglChoosePixelFormatARB function (it is an extension) + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB")); + if (wglChoosePixelFormatARB) + { + // Define the basic attributes we want for our window + int intAttributes[] = + { + WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, + WGL_SUPPORT_OPENGL_ARB, GL_TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_DOUBLE_BUFFER_ARB, GL_TRUE, + WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? GL_TRUE : GL_FALSE), + WGL_SAMPLES_ARB, static_cast<int>(m_settings.antialiasingLevel), + 0, 0 + }; + + // Let's check how many formats are supporting our requirements + int formats[128]; + UINT nbFormats; + float floatAttributes[] = {0, 0}; + bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; + while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0) + { + // Decrease the antialiasing level until we find a valid one + m_settings.antialiasingLevel--; + intAttributes[11] = m_settings.antialiasingLevel; + isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; + } + + // Get the best format among the returned ones + if (isValid && (nbFormats > 0)) + { + int bestScore = 0xFFFF; + for (UINT i = 0; i < nbFormats; ++i) + { + // Get the current format's attributes + PIXELFORMATDESCRIPTOR attributes; + attributes.nSize = sizeof(attributes); + attributes.nVersion = 1; + DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes); + + // Evaluate the current configuration + int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; + int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel); + + // Keep it if it's better than the current best + if (score < bestScore) + { + bestScore = score; + bestFormat = formats[i]; + } + } + } + } + else + { + // wglChoosePixelFormatARB not supported ; disabling antialiasing + err() << "Antialiasing is not supported ; it will be disabled" << std::endl; + m_settings.antialiasingLevel = 0; + } + } + + // Find a pixel format with no antialiasing, if not needed or not supported + if (bestFormat == 0) + { + // Setup a pixel format descriptor from the rendering settings + PIXELFORMATDESCRIPTOR descriptor; + ZeroMemory(&descriptor, sizeof(descriptor)); + descriptor.nSize = sizeof(descriptor); + descriptor.nVersion = 1; + descriptor.iLayerType = PFD_MAIN_PLANE; + descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + descriptor.iPixelType = PFD_TYPE_RGBA; + descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel); + descriptor.cDepthBits = static_cast<BYTE>(m_settings.depthBits); + descriptor.cStencilBits = static_cast<BYTE>(m_settings.stencilBits); + descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0; + + // Get the pixel format that best matches our requirements + bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor); + if (bestFormat == 0) + { + err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; + return; + } + } + + // Extract the depth and stencil bits from the chosen format + PIXELFORMATDESCRIPTOR actualFormat; + actualFormat.nSize = sizeof(actualFormat); + actualFormat.nVersion = 1; + DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat); + m_settings.depthBits = actualFormat.cDepthBits; + m_settings.stencilBits = actualFormat.cStencilBits; + + // Set the chosen pixel format + if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat)) + { + err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; + return; + } + + // Get the context to share display lists with + HGLRC sharedContext = shared ? shared->m_context : NULL; + + // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) + while (!m_context && (m_settings.majorVersion >= 3)) + { + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB")); + if (wglCreateContextAttribsARB) + { + int attributes[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), + WGL_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0, 0 + }; + m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes); + } + + // If we couldn't create the context, lower the version number and try again -- stop at 3.0 + // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care + if (!m_context) + { + if (m_settings.minorVersion > 0) + { + // If the minor version is not 0, we decrease it and try again + m_settings.minorVersion--; + } + else + { + // If the minor version is 0, we decrease the major version + m_settings.majorVersion--; + m_settings.minorVersion = 9; + } + } + } + + // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context + if (!m_context) + { + // set the context version to 2.0 (arbitrary) + m_settings.majorVersion = 2; + m_settings.minorVersion = 0; + + m_context = wglCreateContext(m_deviceContext); + if (!m_context) + { + err() << "Failed to create an OpenGL context for this window" << std::endl; + return; + } + + // Share this context with others + if (sharedContext) + { + // wglShareLists doesn't seem to be thread-safe + static Mutex mutex; + Lock lock(mutex); + + if (!wglShareLists(sharedContext, m_context)) + err() << "Failed to share the OpenGL context" << std::endl; + } + } +} + +} // namespace priv + +} // namespace sf diff --git a/src/SFML/Window/Win32/WglContext.hpp b/src/SFML/Window/Win32/WglContext.hpp index 3fa1c3a..75ef4d5 100644 --- a/src/SFML/Window/Win32/WglContext.hpp +++ b/src/SFML/Window/Win32/WglContext.hpp @@ -1,136 +1,136 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-#ifndef SFML_WGLCONTEXT_HPP
-#define SFML_WGLCONTEXT_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/GlContext.hpp>
-#include <SFML/OpenGL.hpp>
-#include <windows.h>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief Windows (WGL) implementation of OpenGL contexts
-///
-////////////////////////////////////////////////////////////
-class WglContext : public GlContext
-{
-public :
-
- ////////////////////////////////////////////////////////////
- /// \brief Create a new default context
- ///
- /// \param shared Context to share the new one with (can be NULL)
- ///
- ////////////////////////////////////////////////////////////
- WglContext(WglContext* shared);
-
- ////////////////////////////////////////////////////////////
- /// \brief Create a new context attached to a window
- ///
- /// \param shared Context to share the new one with
- /// \param settings Creation parameters
- /// \param owner Pointer to the owner window
- /// \param bitsPerPixel Pixel depth, in bits per pixel
- ///
- ////////////////////////////////////////////////////////////
- WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
-
- ////////////////////////////////////////////////////////////
- /// \brief Create a new context that embeds its own rendering target
- ///
- /// \param shared Context to share the new one with
- /// \param settings Creation parameters
- /// \param width Back buffer width, in pixels
- /// \param height Back buffer height, in pixels
- ///
- ////////////////////////////////////////////////////////////
- WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height);
-
- ////////////////////////////////////////////////////////////
- /// \brief Destructor
- ///
- ////////////////////////////////////////////////////////////
- ~WglContext();
-
- ////////////////////////////////////////////////////////////
- /// \brief Activate the context as the current target for rendering
- ///
- /// \return True on success, false if any error happened
- ///
- ////////////////////////////////////////////////////////////
- virtual bool makeCurrent();
-
- ////////////////////////////////////////////////////////////
- /// \brief Display what has been rendered to the context so far
- ///
- ////////////////////////////////////////////////////////////
- virtual void display();
-
- ////////////////////////////////////////////////////////////
- /// \brief Enable or disable vertical synchronization
- ///
- /// Activating vertical synchronization will limit the number
- /// of frames displayed to the refresh rate of the monitor.
- /// This can avoid some visual artifacts, and limit the framerate
- /// to a good value (but not constant across different computers).
- ///
- /// \param enabled : True to enable v-sync, false to deactivate
- ///
- ////////////////////////////////////////////////////////////
- virtual void setVerticalSyncEnabled(bool enabled);
-
-private :
-
- ////////////////////////////////////////////////////////////
- /// \brief Create the context
- ///
- /// \param shared Context to share the new one with (can be NULL)
- /// \param bitsPerPixel Pixel depth, in bits per pixel
- /// \param settings Creation parameters
- ///
- ////////////////////////////////////////////////////////////
- void createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings);
-
- ////////////////////////////////////////////////////////////
- // Member data
- ////////////////////////////////////////////////////////////
- HWND m_window; ///< Window to which the context is attached
- HDC m_deviceContext; ///< Device context associated to the context
- HGLRC m_context; ///< OpenGL context
- bool m_ownsWindow; ///< Do we own the target window?
-};
-
-} // namespace priv
-
-} // namespace sf
-
-#endif // SFML_WGLCONTEXT_HPP
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WGLCONTEXT_HPP +#define SFML_WGLCONTEXT_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/GlContext.hpp> +#include <SFML/OpenGL.hpp> +#include <windows.h> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows (WGL) implementation of OpenGL contexts +/// +//////////////////////////////////////////////////////////// +class WglContext : public GlContext +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Create a new default context + /// + /// \param shared Context to share the new one with (can be NULL) + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context attached to a window + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param owner Pointer to the owner window + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); + + //////////////////////////////////////////////////////////// + /// \brief Create a new context that embeds its own rendering target + /// + /// \param shared Context to share the new one with + /// \param settings Creation parameters + /// \param width Back buffer width, in pixels + /// \param height Back buffer height, in pixels + /// + //////////////////////////////////////////////////////////// + WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~WglContext(); + + //////////////////////////////////////////////////////////// + /// \brief Activate the context as the current target for rendering + /// + /// \return True on success, false if any error happened + /// + //////////////////////////////////////////////////////////// + virtual bool makeCurrent(); + + //////////////////////////////////////////////////////////// + /// \brief Display what has been rendered to the context so far + /// + //////////////////////////////////////////////////////////// + virtual void display(); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable vertical synchronization + /// + /// Activating vertical synchronization will limit the number + /// of frames displayed to the refresh rate of the monitor. + /// This can avoid some visual artifacts, and limit the framerate + /// to a good value (but not constant across different computers). + /// + /// \param enabled: True to enable v-sync, false to deactivate + /// + //////////////////////////////////////////////////////////// + virtual void setVerticalSyncEnabled(bool enabled); + +private: + + //////////////////////////////////////////////////////////// + /// \brief Create the context + /// + /// \param shared Context to share the new one with (can be NULL) + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// \param settings Creation parameters + /// + //////////////////////////////////////////////////////////// + void createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + HWND m_window; ///< Window to which the context is attached + HDC m_deviceContext; ///< Device context associated to the context + HGLRC m_context; ///< OpenGL context + bool m_ownsWindow; ///< Do we own the target window? +}; + +} // namespace priv + +} // namespace sf + +#endif // SFML_WGLCONTEXT_HPP diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 4c83cae..69fe2ea 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -1,939 +1,1025 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#ifdef _WIN32_WINDOWS
- #undef _WIN32_WINDOWS
-#endif
-#ifdef _WIN32_WINNT
- #undef _WIN32_WINNT
-#endif
-#define _WIN32_WINDOWS 0x0501
-#define _WIN32_WINNT 0x0501
-#include <SFML/Window/Win32/WindowImplWin32.hpp>
-#include <SFML/Window/WindowStyle.hpp>
-#include <GL/gl.h>
-#include <SFML/System/Err.hpp>
-#include <SFML/System/Utf.hpp>
-#include <vector>
-
-// MinGW lacks the definition of some Win32 constants
-#ifndef XBUTTON1
- #define XBUTTON1 0x0001
-#endif
-#ifndef XBUTTON2
- #define XBUTTON2 0x0002
-#endif
-#ifndef MAPVK_VK_TO_VSC
- #define MAPVK_VK_TO_VSC (0)
-#endif
-
-
-namespace
-{
- unsigned int windowCount = 0;
- const char* classNameA = "SFML_Window";
- const wchar_t* classNameW = L"SFML_Window";
- sf::priv::WindowImplWin32* fullscreenWindow = NULL;
-}
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32(WindowHandle handle) :
-m_handle (handle),
-m_callback (0),
-m_cursor (NULL),
-m_icon (NULL),
-m_keyRepeatEnabled(true),
-m_lastSize (0, 0),
-m_resizing (false),
-m_surrogate (0)
-{
- if (m_handle)
- {
- // We change the event procedure of the control (it is important to save the old one)
- SetWindowLongPtr(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- m_callback = SetWindowLongPtr(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WindowImplWin32::globalOnEvent));
- }
-}
-
-
-////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
-m_handle (NULL),
-m_callback (0),
-m_cursor (NULL),
-m_icon (NULL),
-m_keyRepeatEnabled(true),
-m_lastSize (mode.width, mode.height),
-m_resizing (false),
-m_surrogate (0)
-{
- // Register the window class at first call
- if (windowCount == 0)
- registerWindowClass();
-
- // Compute position and size
- HDC screenDC = GetDC(NULL);
- int left = (GetDeviceCaps(screenDC, HORZRES) - static_cast<int>(mode.width)) / 2;
- int top = (GetDeviceCaps(screenDC, VERTRES) - static_cast<int>(mode.height)) / 2;
- int width = mode.width;
- int height = mode.height;
- ReleaseDC(NULL, screenDC);
-
- // Choose the window style according to the Style parameter
- DWORD win32Style = WS_VISIBLE;
- if (style == Style::None)
- {
- win32Style |= WS_POPUP;
- }
- else
- {
- if (style & Style::Titlebar) win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
- if (style & Style::Resize) win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
- if (style & Style::Close) win32Style |= WS_SYSMENU;
- }
-
- // In windowed mode, adjust width and height so that window will have the requested client area
- bool fullscreen = (style & Style::Fullscreen) != 0;
- if (!fullscreen)
- {
- RECT rectangle = {0, 0, width, height};
- AdjustWindowRect(&rectangle, win32Style, false);
- width = rectangle.right - rectangle.left;
- height = rectangle.bottom - rectangle.top;
- }
-
- // Create the window
- if (hasUnicodeSupport())
- {
- m_handle = CreateWindowW(classNameW, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
- }
- else
- {
- m_handle = CreateWindowA(classNameA, title.toAnsiString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
- }
-
- // By default, the OS limits the size of the window the the desktop size,
- // we have to resize it after creation to apply the real size
- setSize(Vector2u(mode.width, mode.height));
-
- // Switch to fullscreen if requested
- if (fullscreen)
- switchToFullscreen(mode);
-
- // Increment window count
- windowCount++;
-}
-
-
-////////////////////////////////////////////////////////////
-WindowImplWin32::~WindowImplWin32()
-{
- // Destroy the custom icon, if any
- if (m_icon)
- DestroyIcon(m_icon);
-
- if (!m_callback)
- {
- // Destroy the window
- if (m_handle)
- DestroyWindow(m_handle);
-
- // Decrement the window count
- windowCount--;
-
- // Unregister window class if we were the last window
- if (windowCount == 0)
- {
- if (hasUnicodeSupport())
- {
- UnregisterClassW(classNameW, GetModuleHandle(NULL));
- }
- else
- {
- UnregisterClassA(classNameA, GetModuleHandle(NULL));
- }
- }
- }
- else
- {
- // The window is external : remove the hook on its message callback
- SetWindowLongPtr(m_handle, GWLP_WNDPROC, m_callback);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-WindowHandle WindowImplWin32::getSystemHandle() const
-{
- return m_handle;
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::processEvents()
-{
- // We process the window events only if we own it
- if (!m_callback)
- {
- MSG message;
- while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&message);
- DispatchMessage(&message);
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////
-Vector2i WindowImplWin32::getPosition() const
-{
- RECT rect;
- GetWindowRect(m_handle, &rect);
-
- return Vector2i(rect.left, rect.top);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setPosition(const Vector2i& position)
-{
- SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
-}
-
-
-////////////////////////////////////////////////////////////
-Vector2u WindowImplWin32::getSize() const
-{
- RECT rect;
- GetClientRect(m_handle, &rect);
-
- return Vector2u(rect.right - rect.left, rect.bottom - rect.top);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setSize(const Vector2u& size)
-{
- // SetWindowPos wants the total size of the window (including title bar and borders),
- // so we have to compute it
- RECT rectangle = {0, 0, static_cast<long>(size.x), static_cast<long>(size.y)};
- AdjustWindowRect(&rectangle, GetWindowLong(m_handle, GWL_STYLE), false);
- int width = rectangle.right - rectangle.left;
- int height = rectangle.bottom - rectangle.top;
-
- SetWindowPos(m_handle, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setTitle(const String& title)
-{
- if (hasUnicodeSupport())
- {
- SetWindowTextW(m_handle, title.toWideString().c_str());
- }
- else
- {
- SetWindowTextA(m_handle, title.toAnsiString().c_str());
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setIcon(unsigned int width, unsigned int height, const Uint8* pixels)
-{
- // First destroy the previous one
- if (m_icon)
- DestroyIcon(m_icon);
-
- // Windows wants BGRA pixels: swap red and blue channels
- std::vector<Uint8> iconPixels(width * height * 4);
- for (std::size_t i = 0; i < iconPixels.size() / 4; ++i)
- {
- iconPixels[i * 4 + 0] = pixels[i * 4 + 2];
- iconPixels[i * 4 + 1] = pixels[i * 4 + 1];
- iconPixels[i * 4 + 2] = pixels[i * 4 + 0];
- iconPixels[i * 4 + 3] = pixels[i * 4 + 3];
- }
-
- // Create the icon from the pixel array
- m_icon = CreateIcon(GetModuleHandle(NULL), width, height, 1, 32, NULL, &iconPixels[0]);
-
- // Set it as both big and small icon of the window
- if (m_icon)
- {
- SendMessage(m_handle, WM_SETICON, ICON_BIG, (LPARAM)m_icon);
- SendMessage(m_handle, WM_SETICON, ICON_SMALL, (LPARAM)m_icon);
- }
- else
- {
- err() << "Failed to set the window's icon" << std::endl;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setVisible(bool visible)
-{
- ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setMouseCursorVisible(bool visible)
-{
- if (visible)
- m_cursor = LoadCursor(NULL, IDC_ARROW);
- else
- m_cursor = NULL;
-
- SetCursor(m_cursor);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
-{
- m_keyRepeatEnabled = enabled;
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::registerWindowClass()
-{
- if (hasUnicodeSupport())
- {
- WNDCLASSW windowClass;
- windowClass.style = 0;
- windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent;
- windowClass.cbClsExtra = 0;
- windowClass.cbWndExtra = 0;
- windowClass.hInstance = GetModuleHandle(NULL);
- windowClass.hIcon = NULL;
- windowClass.hCursor = 0;
- windowClass.hbrBackground = 0;
- windowClass.lpszMenuName = NULL;
- windowClass.lpszClassName = classNameW;
- RegisterClassW(&windowClass);
- }
- else
- {
- WNDCLASSA windowClass;
- windowClass.style = 0;
- windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent;
- windowClass.cbClsExtra = 0;
- windowClass.cbWndExtra = 0;
- windowClass.hInstance = GetModuleHandle(NULL);
- windowClass.hIcon = NULL;
- windowClass.hCursor = 0;
- windowClass.hbrBackground = 0;
- windowClass.lpszMenuName = NULL;
- windowClass.lpszClassName = classNameA;
- RegisterClassA(&windowClass);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::switchToFullscreen(const VideoMode& mode)
-{
- DEVMODE devMode;
- devMode.dmSize = sizeof(devMode);
- devMode.dmPelsWidth = mode.width;
- devMode.dmPelsHeight = mode.height;
- devMode.dmBitsPerPel = mode.bitsPerPixel;
- devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
-
- // Apply fullscreen mode
- if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
- {
- err() << "Failed to change display mode for fullscreen" << std::endl;
- return;
- }
-
- // Make the window flags compatible with fullscreen mode
- SetWindowLong(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- SetWindowLong(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
-
- // Resize the window so that it fits the entire screen
- SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED);
- ShowWindow(m_handle, SW_SHOW);
-
- // Set "this" as the current fullscreen window
- fullscreenWindow = this;
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::cleanup()
-{
- // Restore the previous video mode (in case we were running in fullscreen)
- if (fullscreenWindow == this)
- {
- ChangeDisplaySettings(NULL, 0);
- fullscreenWindow = NULL;
- }
-
- // Unhide the mouse cursor (in case it was hidden)
- setMouseCursorVisible(true);
-}
-
-
-////////////////////////////////////////////////////////////
-void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
-{
- // Don't process any message until window is created
- if (m_handle == NULL)
- return;
-
- switch (message)
- {
- // Destroy event
- case WM_DESTROY :
- {
- // Here we must cleanup resources !
- cleanup();
- break;
- }
-
- // Set cursor event
- case WM_SETCURSOR :
- {
- // The mouse has moved, if the cursor is in our window we must refresh the cursor
- if (LOWORD(lParam) == HTCLIENT)
- SetCursor(m_cursor);
-
- break;
- }
-
- // Close event
- case WM_CLOSE :
- {
- Event event;
- event.type = Event::Closed;
- pushEvent(event);
- break;
- }
-
- // Resize event
- case WM_SIZE :
- {
- // Consider only events triggered by a maximize or a un-maximize
- if (wParam != SIZE_MINIMIZED && !m_resizing && m_lastSize != getSize())
- {
- // Update the last handled size
- m_lastSize = getSize();
-
- // Push a resize event
- Event event;
- event.type = Event::Resized;
- event.size.width = m_lastSize.x;
- event.size.height = m_lastSize.y;
- pushEvent(event);
- }
- break;
- }
-
- // Start resizing
- case WM_ENTERSIZEMOVE:
- {
- m_resizing = true;
- break;
- }
-
- // Stop resizing
- case WM_EXITSIZEMOVE:
- {
- m_resizing = false;
-
- // Ignore cases where the window has only been moved
- if(m_lastSize != getSize())
- {
- // Update the last handled size
- m_lastSize = getSize();
-
- // Push a resize event
- Event event;
- event.type = Event::Resized;
- event.size.width = m_lastSize.x;
- event.size.height = m_lastSize.y;
- pushEvent(event);
- }
- break;
- }
-
- // The system request the min/max window size and position
- case WM_GETMINMAXINFO :
- {
- // We override the returned information to remove the default limit
- // (the OS doesn't allow windows bigger than the desktop by default)
- MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
- info->ptMaxTrackSize.x = 50000;
- info->ptMaxTrackSize.y = 50000;
- break;
- }
-
- // Gain focus event
- case WM_SETFOCUS :
- {
- Event event;
- event.type = Event::GainedFocus;
- pushEvent(event);
- break;
- }
-
- // Lost focus event
- case WM_KILLFOCUS :
- {
- Event event;
- event.type = Event::LostFocus;
- pushEvent(event);
- break;
- }
-
- // Text event
- case WM_CHAR :
- {
- if (m_keyRepeatEnabled || ((lParam & (1 << 30)) == 0))
- {
- // Get the code of the typed character
- Uint32 character = static_cast<Uint32>(wParam);
-
- // Check if it is the first part of a surrogate pair, or a regular character
- if ((character >= 0xD800) && (character <= 0xDBFF))
- {
- // First part of a surrogate pair: store it and wait for the second one
- m_surrogate = static_cast<Uint16>(character);
- }
- else
- {
-
- // Check if it is the second part of a surrogate pair, or a regular character
- if ((character >= 0xDC00) && (character <= 0xDFFF))
- {
- // Convert the UTF-16 surrogate pair to a single UTF-32 value
- Uint16 utf16[] = {m_surrogate, static_cast<Uint16>(character)};
- sf::Utf16::toUtf32(utf16, utf16 + 2, &character);
- m_surrogate = 0;
- }
-
- // Send a TextEntered event
- Event event;
- event.type = Event::TextEntered;
- event.text.unicode = character;
- pushEvent(event);
- }
- }
- break;
- }
-
- // Keydown event
- case WM_KEYDOWN :
- case WM_SYSKEYDOWN :
- {
- if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0))
- {
- Event event;
- event.type = Event::KeyPressed;
- event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
- event.key.code = virtualKeyCodeToSF(wParam, lParam);
- pushEvent(event);
- }
- break;
- }
-
- // Keyup event
- case WM_KEYUP :
- case WM_SYSKEYUP :
- {
- Event event;
- event.type = Event::KeyReleased;
- event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
- event.key.code = virtualKeyCodeToSF(wParam, lParam);
- pushEvent(event);
- break;
- }
-
- // Mouse wheel event
- case WM_MOUSEWHEEL :
- {
- // Mouse position is in screen coordinates, convert it to window coordinates
- POINT position;
- position.x = static_cast<Int16>(LOWORD(lParam));
- position.y = static_cast<Int16>(HIWORD(lParam));
- ScreenToClient(m_handle, &position);
-
- Event event;
- event.type = Event::MouseWheelMoved;
- event.mouseWheel.delta = static_cast<Int16>(HIWORD(wParam)) / 120;
- event.mouseWheel.x = position.x;
- event.mouseWheel.y = position.y;
- pushEvent(event);
- break;
- }
-
- // Mouse left button down event
- case WM_LBUTTONDOWN :
- {
- Event event;
- event.type = Event::MouseButtonPressed;
- event.mouseButton.button = Mouse::Left;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse left button up event
- case WM_LBUTTONUP :
- {
- Event event;
- event.type = Event::MouseButtonReleased;
- event.mouseButton.button = Mouse::Left;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse right button down event
- case WM_RBUTTONDOWN :
- {
- Event event;
- event.type = Event::MouseButtonPressed;
- event.mouseButton.button = Mouse::Right;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse right button up event
- case WM_RBUTTONUP :
- {
- Event event;
- event.type = Event::MouseButtonReleased;
- event.mouseButton.button = Mouse::Right;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse wheel button down event
- case WM_MBUTTONDOWN :
- {
- Event event;
- event.type = Event::MouseButtonPressed;
- event.mouseButton.button = Mouse::Middle;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse wheel button up event
- case WM_MBUTTONUP :
- {
- Event event;
- event.type = Event::MouseButtonReleased;
- event.mouseButton.button = Mouse::Middle;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse X button down event
- case WM_XBUTTONDOWN :
- {
- Event event;
- event.type = Event::MouseButtonPressed;
- event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse X button up event
- case WM_XBUTTONUP :
- {
- Event event;
- event.type = Event::MouseButtonReleased;
- event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
- event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
- event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
- pushEvent(event);
- break;
- }
-
- // Mouse move event
- case WM_MOUSEMOVE :
- {
- // Extract the mouse local coordinates
- int x = static_cast<Int16>(LOWORD(lParam));
- int y = static_cast<Int16>(HIWORD(lParam));
-
- // Get the client area of the window
- RECT area;
- GetClientRect(m_handle, &area);
-
- // Check the mouse position against the window
- if ((x < area.left) || (x > area.right) || (y < area.top) || (y > area.bottom))
- {
- // Mouse is outside
-
- // Release the mouse capture
- ReleaseCapture();
-
- // Generate a MouseLeft event
- Event event;
- event.type = Event::MouseLeft;
- pushEvent(event);
- }
- else
- {
- // Mouse is inside
- if (GetCapture() != m_handle)
- {
- // Mouse was previously outside the window
-
- // Capture the mouse
- SetCapture(m_handle);
-
- // Generate a MouseEntered event
- Event event;
- event.type = Event::MouseEntered;
- pushEvent(event);
- }
-
- // Generate a MouseMove event
- Event event;
- event.type = Event::MouseMoved;
- event.mouseMove.x = x;
- event.mouseMove.y = y;
- pushEvent(event);
- break;
- }
- }
- }
-}
-
-
-////////////////////////////////////////////////////////////
-Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags)
-{
- switch (key)
- {
- // Check the scancode to distinguish between left and right shift
- case VK_SHIFT :
- {
- static UINT lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
- UINT scancode = static_cast<UINT>((flags & (0xFF << 16)) >> 16);
- return scancode == lShift ? Keyboard::LShift : Keyboard::RShift;
- }
-
- // Check the "extended" flag to distinguish between left and right alt
- case VK_MENU : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RAlt : Keyboard::LAlt;
-
- // Check the "extended" flag to distinguish between left and right control
- case VK_CONTROL : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RControl : Keyboard::LControl;
-
- // Other keys are reported properly
- case VK_LWIN : return Keyboard::LSystem;
- case VK_RWIN : return Keyboard::RSystem;
- case VK_APPS : return Keyboard::Menu;
- case VK_OEM_1 : return Keyboard::SemiColon;
- case VK_OEM_2 : return Keyboard::Slash;
- case VK_OEM_PLUS : return Keyboard::Equal;
- case VK_OEM_MINUS : return Keyboard::Dash;
- case VK_OEM_4 : return Keyboard::LBracket;
- case VK_OEM_6 : return Keyboard::RBracket;
- case VK_OEM_COMMA : return Keyboard::Comma;
- case VK_OEM_PERIOD : return Keyboard::Period;
- case VK_OEM_7 : return Keyboard::Quote;
- case VK_OEM_5 : return Keyboard::BackSlash;
- case VK_OEM_3 : return Keyboard::Tilde;
- case VK_ESCAPE : return Keyboard::Escape;
- case VK_SPACE : return Keyboard::Space;
- case VK_RETURN : return Keyboard::Return;
- case VK_BACK : return Keyboard::BackSpace;
- case VK_TAB : return Keyboard::Tab;
- case VK_PRIOR : return Keyboard::PageUp;
- case VK_NEXT : return Keyboard::PageDown;
- case VK_END : return Keyboard::End;
- case VK_HOME : return Keyboard::Home;
- case VK_INSERT : return Keyboard::Insert;
- case VK_DELETE : return Keyboard::Delete;
- case VK_ADD : return Keyboard::Add;
- case VK_SUBTRACT : return Keyboard::Subtract;
- case VK_MULTIPLY : return Keyboard::Multiply;
- case VK_DIVIDE : return Keyboard::Divide;
- case VK_PAUSE : return Keyboard::Pause;
- case VK_F1 : return Keyboard::F1;
- case VK_F2 : return Keyboard::F2;
- case VK_F3 : return Keyboard::F3;
- case VK_F4 : return Keyboard::F4;
- case VK_F5 : return Keyboard::F5;
- case VK_F6 : return Keyboard::F6;
- case VK_F7 : return Keyboard::F7;
- case VK_F8 : return Keyboard::F8;
- case VK_F9 : return Keyboard::F9;
- case VK_F10 : return Keyboard::F10;
- case VK_F11 : return Keyboard::F11;
- case VK_F12 : return Keyboard::F12;
- case VK_F13 : return Keyboard::F13;
- case VK_F14 : return Keyboard::F14;
- case VK_F15 : return Keyboard::F15;
- case VK_LEFT : return Keyboard::Left;
- case VK_RIGHT : return Keyboard::Right;
- case VK_UP : return Keyboard::Up;
- case VK_DOWN : return Keyboard::Down;
- case VK_NUMPAD0 : return Keyboard::Numpad0;
- case VK_NUMPAD1 : return Keyboard::Numpad1;
- case VK_NUMPAD2 : return Keyboard::Numpad2;
- case VK_NUMPAD3 : return Keyboard::Numpad3;
- case VK_NUMPAD4 : return Keyboard::Numpad4;
- case VK_NUMPAD5 : return Keyboard::Numpad5;
- case VK_NUMPAD6 : return Keyboard::Numpad6;
- case VK_NUMPAD7 : return Keyboard::Numpad7;
- case VK_NUMPAD8 : return Keyboard::Numpad8;
- case VK_NUMPAD9 : return Keyboard::Numpad9;
- case 'A' : return Keyboard::A;
- case 'Z' : return Keyboard::Z;
- case 'E' : return Keyboard::E;
- case 'R' : return Keyboard::R;
- case 'T' : return Keyboard::T;
- case 'Y' : return Keyboard::Y;
- case 'U' : return Keyboard::U;
- case 'I' : return Keyboard::I;
- case 'O' : return Keyboard::O;
- case 'P' : return Keyboard::P;
- case 'Q' : return Keyboard::Q;
- case 'S' : return Keyboard::S;
- case 'D' : return Keyboard::D;
- case 'F' : return Keyboard::F;
- case 'G' : return Keyboard::G;
- case 'H' : return Keyboard::H;
- case 'J' : return Keyboard::J;
- case 'K' : return Keyboard::K;
- case 'L' : return Keyboard::L;
- case 'M' : return Keyboard::M;
- case 'W' : return Keyboard::W;
- case 'X' : return Keyboard::X;
- case 'C' : return Keyboard::C;
- case 'V' : return Keyboard::V;
- case 'B' : return Keyboard::B;
- case 'N' : return Keyboard::N;
- case '0' : return Keyboard::Num0;
- case '1' : return Keyboard::Num1;
- case '2' : return Keyboard::Num2;
- case '3' : return Keyboard::Num3;
- case '4' : return Keyboard::Num4;
- case '5' : return Keyboard::Num5;
- case '6' : return Keyboard::Num6;
- case '7' : return Keyboard::Num7;
- case '8' : return Keyboard::Num8;
- case '9' : return Keyboard::Num9;
- }
-
- return Keyboard::Unknown;
-}
-
-
-////////////////////////////////////////////////////////////
-bool WindowImplWin32::hasUnicodeSupport()
-{
- OSVERSIONINFO version;
- ZeroMemory(&version, sizeof(version));
- version.dwOSVersionInfoSize = sizeof(version);
-
- if (GetVersionEx(&version))
- {
- return version.dwPlatformId == VER_PLATFORM_WIN32_NT;
- }
- else
- {
- return false;
- }
-}
-
-
-////////////////////////////////////////////////////////////
-LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
-{
- // Associate handle and Window instance when the creation message is received
- if (message == WM_CREATE)
- {
- // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow)
- LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams;
-
- // Set as the "user data" parameter of the window
- SetWindowLongPtr(handle, GWLP_USERDATA, window);
- }
-
- // Get the WindowImpl instance corresponding to the window handle
- WindowImplWin32* window = handle ? reinterpret_cast<WindowImplWin32*>(GetWindowLongPtr(handle, GWLP_USERDATA)) : NULL;
-
- // Forward the event to the appropriate function
- if (window)
- {
- window->processEvent(message, wParam, lParam);
-
- if (window->m_callback)
- return CallWindowProc(reinterpret_cast<WNDPROC>(window->m_callback), handle, message, wParam, lParam);
- }
-
- // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window
- if (message == WM_CLOSE)
- return 0;
-
- // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus
- if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU))
- return 0;
-
- static const bool hasUnicode = hasUnicodeSupport();
- return hasUnicode ? DefWindowProcW(handle, message, wParam, lParam) :
- DefWindowProcA(handle, message, wParam, lParam);
-}
-
-} // namespace priv
-
-} // namespace sf
-
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#ifdef _WIN32_WINDOWS + #undef _WIN32_WINDOWS +#endif +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINDOWS 0x0501 +#define _WIN32_WINNT 0x0501 +#define WINVER 0x0501 +#include <SFML/Window/Win32/WindowImplWin32.hpp> +#include <SFML/Window/WindowStyle.hpp> +#include <GL/gl.h> +#include <SFML/System/Err.hpp> +#include <SFML/System/Utf.hpp> +#include <vector> + +// MinGW lacks the definition of some Win32 constants +#ifndef XBUTTON1 + #define XBUTTON1 0x0001 +#endif +#ifndef XBUTTON2 + #define XBUTTON2 0x0002 +#endif +#ifndef MAPVK_VK_TO_VSC + #define MAPVK_VK_TO_VSC (0) +#endif + + +namespace +{ + unsigned int windowCount = 0; + const wchar_t* className = L"SFML_Window"; + sf::priv::WindowImplWin32* fullscreenWindow = NULL; + + void setProcessDpiAware() + { + // Try SetProcessDpiAwareness first + HINSTANCE shCoreDll = LoadLibrary(L"Shcore.dll"); + + if (shCoreDll) + { + enum ProcessDpiAwareness + { + ProcessDpiUnaware = 0, + ProcessSystemDpiAware = 1, + ProcessPerMonitorDpiAware = 2 + }; + + typedef HRESULT (WINAPI* SetProcessDpiAwarenessFuncType)(ProcessDpiAwareness); + SetProcessDpiAwarenessFuncType SetProcessDpiAwarenessFunc = reinterpret_cast<SetProcessDpiAwarenessFuncType>(GetProcAddress(shCoreDll, "SetProcessDpiAwareness")); + + if (SetProcessDpiAwarenessFunc) + { + // We only check for E_INVALIDARG because we would get + // E_ACCESSDENIED if the DPI was already set previously + // and S_OK means the call was successful + if (SetProcessDpiAwarenessFunc(ProcessSystemDpiAware) == E_INVALIDARG) + { + sf::err() << "Failed to set process DPI awareness" << std::endl; + } + else + { + FreeLibrary(shCoreDll); + return; + } + } + + FreeLibrary(shCoreDll); + } + + // Fall back to SetProcessDPIAware if SetProcessDpiAwareness + // is not available on this system + HINSTANCE user32Dll = LoadLibrary(L"user32.dll"); + + if (user32Dll) + { + typedef BOOL (WINAPI* SetProcessDPIAwareFuncType)(void); + SetProcessDPIAwareFuncType SetProcessDPIAwareFunc = reinterpret_cast<SetProcessDPIAwareFuncType>(GetProcAddress(user32Dll, "SetProcessDPIAware")); + + if (SetProcessDPIAwareFunc) + { + if (!SetProcessDPIAwareFunc()) + sf::err() << "Failed to set process DPI awareness" << std::endl; + } + + FreeLibrary(user32Dll); + } + } +} + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +WindowImplWin32::WindowImplWin32(WindowHandle handle) : +m_handle (handle), +m_callback (0), +m_cursor (NULL), +m_icon (NULL), +m_keyRepeatEnabled(true), +m_lastSize (0, 0), +m_resizing (false), +m_surrogate (0), +m_mouseInside (false) +{ + // Set that this process is DPI aware and can handle DPI scaling + setProcessDpiAware(); + + if (m_handle) + { + // We change the event procedure of the control (it is important to save the old one) + SetWindowLongPtrW(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); + m_callback = SetWindowLongPtrW(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WindowImplWin32::globalOnEvent)); + } +} + + +//////////////////////////////////////////////////////////// +WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) : +m_handle (NULL), +m_callback (0), +m_cursor (NULL), +m_icon (NULL), +m_keyRepeatEnabled(true), +m_lastSize (mode.width, mode.height), +m_resizing (false), +m_surrogate (0), +m_mouseInside (false) +{ + // Set that this process is DPI aware and can handle DPI scaling + setProcessDpiAware(); + + // Register the window class at first call + if (windowCount == 0) + registerWindowClass(); + + // Compute position and size + HDC screenDC = GetDC(NULL); + int left = (GetDeviceCaps(screenDC, HORZRES) - static_cast<int>(mode.width)) / 2; + int top = (GetDeviceCaps(screenDC, VERTRES) - static_cast<int>(mode.height)) / 2; + int width = mode.width; + int height = mode.height; + ReleaseDC(NULL, screenDC); + + // Choose the window style according to the Style parameter + DWORD win32Style = WS_VISIBLE; + if (style == Style::None) + { + win32Style |= WS_POPUP; + } + else + { + if (style & Style::Titlebar) win32Style |= WS_CAPTION | WS_MINIMIZEBOX; + if (style & Style::Resize) win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX; + if (style & Style::Close) win32Style |= WS_SYSMENU; + } + + // In windowed mode, adjust width and height so that window will have the requested client area + bool fullscreen = (style & Style::Fullscreen) != 0; + if (!fullscreen) + { + RECT rectangle = {0, 0, width, height}; + AdjustWindowRect(&rectangle, win32Style, false); + width = rectangle.right - rectangle.left; + height = rectangle.bottom - rectangle.top; + } + + // Create the window + m_handle = CreateWindowW(className, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this); + + // By default, the OS limits the size of the window the the desktop size, + // we have to resize it after creation to apply the real size + setSize(Vector2u(mode.width, mode.height)); + + // Switch to fullscreen if requested + if (fullscreen) + switchToFullscreen(mode); + + // Increment window count + windowCount++; +} + + +//////////////////////////////////////////////////////////// +WindowImplWin32::~WindowImplWin32() +{ + // Destroy the custom icon, if any + if (m_icon) + DestroyIcon(m_icon); + + if (!m_callback) + { + // Destroy the window + if (m_handle) + DestroyWindow(m_handle); + + // Decrement the window count + windowCount--; + + // Unregister window class if we were the last window + if (windowCount == 0) + UnregisterClassW(className, GetModuleHandleW(NULL)); + } + else + { + // The window is external: remove the hook on its message callback + SetWindowLongPtrW(m_handle, GWLP_WNDPROC, m_callback); + } +} + + +//////////////////////////////////////////////////////////// +WindowHandle WindowImplWin32::getSystemHandle() const +{ + return m_handle; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::processEvents() +{ + // We process the window events only if we own it + if (!m_callback) + { + MSG message; + while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&message); + DispatchMessageW(&message); + } + } +} + + +//////////////////////////////////////////////////////////// +Vector2i WindowImplWin32::getPosition() const +{ + RECT rect; + GetWindowRect(m_handle, &rect); + + return Vector2i(rect.left, rect.top); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setPosition(const Vector2i& position) +{ + SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + + +//////////////////////////////////////////////////////////// +Vector2u WindowImplWin32::getSize() const +{ + RECT rect; + GetClientRect(m_handle, &rect); + + return Vector2u(rect.right - rect.left, rect.bottom - rect.top); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setSize(const Vector2u& size) +{ + // SetWindowPos wants the total size of the window (including title bar and borders), + // so we have to compute it + RECT rectangle = {0, 0, static_cast<long>(size.x), static_cast<long>(size.y)}; + AdjustWindowRect(&rectangle, GetWindowLong(m_handle, GWL_STYLE), false); + int width = rectangle.right - rectangle.left; + int height = rectangle.bottom - rectangle.top; + + SetWindowPos(m_handle, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setTitle(const String& title) +{ + SetWindowTextW(m_handle, title.toWideString().c_str()); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) +{ + // First destroy the previous one + if (m_icon) + DestroyIcon(m_icon); + + // Windows wants BGRA pixels: swap red and blue channels + std::vector<Uint8> iconPixels(width * height * 4); + for (std::size_t i = 0; i < iconPixels.size() / 4; ++i) + { + iconPixels[i * 4 + 0] = pixels[i * 4 + 2]; + iconPixels[i * 4 + 1] = pixels[i * 4 + 1]; + iconPixels[i * 4 + 2] = pixels[i * 4 + 0]; + iconPixels[i * 4 + 3] = pixels[i * 4 + 3]; + } + + // Create the icon from the pixel array + m_icon = CreateIcon(GetModuleHandleW(NULL), width, height, 1, 32, NULL, &iconPixels[0]); + + // Set it as both big and small icon of the window + if (m_icon) + { + SendMessageW(m_handle, WM_SETICON, ICON_BIG, (LPARAM)m_icon); + SendMessageW(m_handle, WM_SETICON, ICON_SMALL, (LPARAM)m_icon); + } + else + { + err() << "Failed to set the window's icon" << std::endl; + } +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setVisible(bool visible) +{ + ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setMouseCursorVisible(bool visible) +{ + if (visible) + m_cursor = LoadCursorW(NULL, IDC_ARROW); + else + m_cursor = NULL; + + SetCursor(m_cursor); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setKeyRepeatEnabled(bool enabled) +{ + m_keyRepeatEnabled = enabled; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::requestFocus() +{ + // Allow focus stealing only within the same process; compare PIDs of current and foreground window + DWORD thisPid = GetWindowThreadProcessId(m_handle, NULL); + DWORD foregroundPid = GetWindowThreadProcessId(GetForegroundWindow(), NULL); + + if (thisPid == foregroundPid) + { + // The window requesting focus belongs to the same process as the current window: steal focus + SetForegroundWindow(m_handle); + } + else + { + // Different process: don't steal focus, but create a taskbar notification ("flash") + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_handle; + info.dwFlags = FLASHW_TRAY; + info.dwTimeout = 0; + info.uCount = 3; + + FlashWindowEx(&info); + } +} + + +//////////////////////////////////////////////////////////// +bool WindowImplWin32::hasFocus() const +{ + return m_handle == GetForegroundWindow(); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::registerWindowClass() +{ + WNDCLASSW windowClass; + windowClass.style = 0; + windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent; + windowClass.cbClsExtra = 0; + windowClass.cbWndExtra = 0; + windowClass.hInstance = GetModuleHandleW(NULL); + windowClass.hIcon = NULL; + windowClass.hCursor = 0; + windowClass.hbrBackground = 0; + windowClass.lpszMenuName = NULL; + windowClass.lpszClassName = className; + RegisterClassW(&windowClass); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::switchToFullscreen(const VideoMode& mode) +{ + DEVMODE devMode; + devMode.dmSize = sizeof(devMode); + devMode.dmPelsWidth = mode.width; + devMode.dmPelsHeight = mode.height; + devMode.dmBitsPerPel = mode.bitsPerPixel; + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + + // Apply fullscreen mode + if (ChangeDisplaySettingsW(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) + { + err() << "Failed to change display mode for fullscreen" << std::endl; + return; + } + + // Make the window flags compatible with fullscreen mode + SetWindowLongW(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowLongW(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW); + + // Resize the window so that it fits the entire screen + SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED); + ShowWindow(m_handle, SW_SHOW); + + // Set "this" as the current fullscreen window + fullscreenWindow = this; +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::cleanup() +{ + // Restore the previous video mode (in case we were running in fullscreen) + if (fullscreenWindow == this) + { + ChangeDisplaySettingsW(NULL, 0); + fullscreenWindow = NULL; + } + + // Unhide the mouse cursor (in case it was hidden) + setMouseCursorVisible(true); + + // No longer track the cursor + setTracking(false); + + // No longer capture the cursor + ReleaseCapture(); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::setTracking(bool track) +{ + TRACKMOUSEEVENT mouseEvent; + mouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + mouseEvent.dwFlags = track ? TME_LEAVE : TME_CANCEL; + mouseEvent.hwndTrack = m_handle; + mouseEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&mouseEvent); +} + + +//////////////////////////////////////////////////////////// +void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam) +{ + // Don't process any message until window is created + if (m_handle == NULL) + return; + + switch (message) + { + // Destroy event + case WM_DESTROY: + { + // Here we must cleanup resources ! + cleanup(); + break; + } + + // Set cursor event + case WM_SETCURSOR: + { + // The mouse has moved, if the cursor is in our window we must refresh the cursor + if (LOWORD(lParam) == HTCLIENT) + SetCursor(m_cursor); + + break; + } + + // Close event + case WM_CLOSE: + { + Event event; + event.type = Event::Closed; + pushEvent(event); + break; + } + + // Resize event + case WM_SIZE: + { + // Consider only events triggered by a maximize or a un-maximize + if (wParam != SIZE_MINIMIZED && !m_resizing && m_lastSize != getSize()) + { + // Update the last handled size + m_lastSize = getSize(); + + // Push a resize event + Event event; + event.type = Event::Resized; + event.size.width = m_lastSize.x; + event.size.height = m_lastSize.y; + pushEvent(event); + } + break; + } + + // Start resizing + case WM_ENTERSIZEMOVE: + { + m_resizing = true; + break; + } + + // Stop resizing + case WM_EXITSIZEMOVE: + { + m_resizing = false; + + // Ignore cases where the window has only been moved + if(m_lastSize != getSize()) + { + // Update the last handled size + m_lastSize = getSize(); + + // Push a resize event + Event event; + event.type = Event::Resized; + event.size.width = m_lastSize.x; + event.size.height = m_lastSize.y; + pushEvent(event); + } + break; + } + + // The system request the min/max window size and position + case WM_GETMINMAXINFO: + { + // We override the returned information to remove the default limit + // (the OS doesn't allow windows bigger than the desktop by default) + MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam); + info->ptMaxTrackSize.x = 50000; + info->ptMaxTrackSize.y = 50000; + break; + } + + // Gain focus event + case WM_SETFOCUS: + { + Event event; + event.type = Event::GainedFocus; + pushEvent(event); + break; + } + + // Lost focus event + case WM_KILLFOCUS: + { + Event event; + event.type = Event::LostFocus; + pushEvent(event); + break; + } + + // Text event + case WM_CHAR: + { + if (m_keyRepeatEnabled || ((lParam & (1 << 30)) == 0)) + { + // Get the code of the typed character + Uint32 character = static_cast<Uint32>(wParam); + + // Check if it is the first part of a surrogate pair, or a regular character + if ((character >= 0xD800) && (character <= 0xDBFF)) + { + // First part of a surrogate pair: store it and wait for the second one + m_surrogate = static_cast<Uint16>(character); + } + else + { + // Check if it is the second part of a surrogate pair, or a regular character + if ((character >= 0xDC00) && (character <= 0xDFFF)) + { + // Convert the UTF-16 surrogate pair to a single UTF-32 value + Uint16 utf16[] = {m_surrogate, static_cast<Uint16>(character)}; + sf::Utf16::toUtf32(utf16, utf16 + 2, &character); + m_surrogate = 0; + } + + // Send a TextEntered event + Event event; + event.type = Event::TextEntered; + event.text.unicode = character; + pushEvent(event); + } + } + break; + } + + // Keydown event + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0)) + { + Event event; + event.type = Event::KeyPressed; + event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; + event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; + event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; + event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); + event.key.code = virtualKeyCodeToSF(wParam, lParam); + pushEvent(event); + } + break; + } + + // Keyup event + case WM_KEYUP: + case WM_SYSKEYUP: + { + Event event; + event.type = Event::KeyReleased; + event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0; + event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0; + event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0; + event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN)); + event.key.code = virtualKeyCodeToSF(wParam, lParam); + pushEvent(event); + break; + } + + // Mouse wheel event + case WM_MOUSEWHEEL: + { + // Mouse position is in screen coordinates, convert it to window coordinates + POINT position; + position.x = static_cast<Int16>(LOWORD(lParam)); + position.y = static_cast<Int16>(HIWORD(lParam)); + ScreenToClient(m_handle, &position); + + Event event; + event.type = Event::MouseWheelMoved; + event.mouseWheel.delta = static_cast<Int16>(HIWORD(wParam)) / 120; + event.mouseWheel.x = position.x; + event.mouseWheel.y = position.y; + pushEvent(event); + break; + } + + // Mouse left button down event + case WM_LBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Left; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse left button up event + case WM_LBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Left; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse right button down event + case WM_RBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Right; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse right button up event + case WM_RBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Right; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse wheel button down event + case WM_MBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = Mouse::Middle; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse wheel button up event + case WM_MBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = Mouse::Middle; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse X button down event + case WM_XBUTTONDOWN: + { + Event event; + event.type = Event::MouseButtonPressed; + event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse X button up event + case WM_XBUTTONUP: + { + Event event; + event.type = Event::MouseButtonReleased; + event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2; + event.mouseButton.x = static_cast<Int16>(LOWORD(lParam)); + event.mouseButton.y = static_cast<Int16>(HIWORD(lParam)); + pushEvent(event); + break; + } + + // Mouse leave event + case WM_MOUSELEAVE: + { + // Avoid this firing a second time in case the cursor is dragged outside + if (m_mouseInside) + { + m_mouseInside = false; + + // Generate a MouseLeft event + Event event; + event.type = Event::MouseLeft; + pushEvent(event); + } + break; + } + + // Mouse move event + case WM_MOUSEMOVE: + { + // Extract the mouse local coordinates + int x = static_cast<Int16>(LOWORD(lParam)); + int y = static_cast<Int16>(HIWORD(lParam)); + + // Get the client area of the window + RECT area; + GetClientRect(m_handle, &area); + + // Capture the mouse in case the user wants to drag it outside + if ((wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0) + { + // Only release the capture if we really have it + if (GetCapture() == m_handle) + ReleaseCapture(); + } + else if (GetCapture() != m_handle) + { + // Set the capture to continue receiving mouse events + SetCapture(m_handle); + } + + // If the cursor is outside the client area... + if ((x < area.left) || (x > area.right) || (y < area.top) || (y > area.bottom)) + { + // and it used to be inside, the mouse left it. + if (m_mouseInside) + { + m_mouseInside = false; + + // No longer care for the mouse leaving the window + setTracking(false); + + // Generate a MouseLeft event + Event event; + event.type = Event::MouseLeft; + pushEvent(event); + } + } + else + { + // and vice-versa + if (!m_mouseInside) + { + m_mouseInside = true; + + // Look for the mouse leaving the window + setTracking(true); + + // Generate a MouseEntered event + Event event; + event.type = Event::MouseEntered; + pushEvent(event); + } + } + + // Generate a MouseMove event + Event event; + event.type = Event::MouseMoved; + event.mouseMove.x = x; + event.mouseMove.y = y; + pushEvent(event); + break; + } + } +} + + +//////////////////////////////////////////////////////////// +Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags) +{ + switch (key) + { + // Check the scancode to distinguish between left and right shift + case VK_SHIFT: + { + static UINT lShift = MapVirtualKeyW(VK_LSHIFT, MAPVK_VK_TO_VSC); + UINT scancode = static_cast<UINT>((flags & (0xFF << 16)) >> 16); + return scancode == lShift ? Keyboard::LShift : Keyboard::RShift; + } + + // Check the "extended" flag to distinguish between left and right alt + case VK_MENU : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RAlt : Keyboard::LAlt; + + // Check the "extended" flag to distinguish between left and right control + case VK_CONTROL : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RControl : Keyboard::LControl; + + // Other keys are reported properly + case VK_LWIN: return Keyboard::LSystem; + case VK_RWIN: return Keyboard::RSystem; + case VK_APPS: return Keyboard::Menu; + case VK_OEM_1: return Keyboard::SemiColon; + case VK_OEM_2: return Keyboard::Slash; + case VK_OEM_PLUS: return Keyboard::Equal; + case VK_OEM_MINUS: return Keyboard::Dash; + case VK_OEM_4: return Keyboard::LBracket; + case VK_OEM_6: return Keyboard::RBracket; + case VK_OEM_COMMA: return Keyboard::Comma; + case VK_OEM_PERIOD: return Keyboard::Period; + case VK_OEM_7: return Keyboard::Quote; + case VK_OEM_5: return Keyboard::BackSlash; + case VK_OEM_3: return Keyboard::Tilde; + case VK_ESCAPE: return Keyboard::Escape; + case VK_SPACE: return Keyboard::Space; + case VK_RETURN: return Keyboard::Return; + case VK_BACK: return Keyboard::BackSpace; + case VK_TAB: return Keyboard::Tab; + case VK_PRIOR: return Keyboard::PageUp; + case VK_NEXT: return Keyboard::PageDown; + case VK_END: return Keyboard::End; + case VK_HOME: return Keyboard::Home; + case VK_INSERT: return Keyboard::Insert; + case VK_DELETE: return Keyboard::Delete; + case VK_ADD: return Keyboard::Add; + case VK_SUBTRACT: return Keyboard::Subtract; + case VK_MULTIPLY: return Keyboard::Multiply; + case VK_DIVIDE: return Keyboard::Divide; + case VK_PAUSE: return Keyboard::Pause; + case VK_F1: return Keyboard::F1; + case VK_F2: return Keyboard::F2; + case VK_F3: return Keyboard::F3; + case VK_F4: return Keyboard::F4; + case VK_F5: return Keyboard::F5; + case VK_F6: return Keyboard::F6; + case VK_F7: return Keyboard::F7; + case VK_F8: return Keyboard::F8; + case VK_F9: return Keyboard::F9; + case VK_F10: return Keyboard::F10; + case VK_F11: return Keyboard::F11; + case VK_F12: return Keyboard::F12; + case VK_F13: return Keyboard::F13; + case VK_F14: return Keyboard::F14; + case VK_F15: return Keyboard::F15; + case VK_LEFT: return Keyboard::Left; + case VK_RIGHT: return Keyboard::Right; + case VK_UP: return Keyboard::Up; + case VK_DOWN: return Keyboard::Down; + case VK_NUMPAD0: return Keyboard::Numpad0; + case VK_NUMPAD1: return Keyboard::Numpad1; + case VK_NUMPAD2: return Keyboard::Numpad2; + case VK_NUMPAD3: return Keyboard::Numpad3; + case VK_NUMPAD4: return Keyboard::Numpad4; + case VK_NUMPAD5: return Keyboard::Numpad5; + case VK_NUMPAD6: return Keyboard::Numpad6; + case VK_NUMPAD7: return Keyboard::Numpad7; + case VK_NUMPAD8: return Keyboard::Numpad8; + case VK_NUMPAD9: return Keyboard::Numpad9; + case 'A': return Keyboard::A; + case 'Z': return Keyboard::Z; + case 'E': return Keyboard::E; + case 'R': return Keyboard::R; + case 'T': return Keyboard::T; + case 'Y': return Keyboard::Y; + case 'U': return Keyboard::U; + case 'I': return Keyboard::I; + case 'O': return Keyboard::O; + case 'P': return Keyboard::P; + case 'Q': return Keyboard::Q; + case 'S': return Keyboard::S; + case 'D': return Keyboard::D; + case 'F': return Keyboard::F; + case 'G': return Keyboard::G; + case 'H': return Keyboard::H; + case 'J': return Keyboard::J; + case 'K': return Keyboard::K; + case 'L': return Keyboard::L; + case 'M': return Keyboard::M; + case 'W': return Keyboard::W; + case 'X': return Keyboard::X; + case 'C': return Keyboard::C; + case 'V': return Keyboard::V; + case 'B': return Keyboard::B; + case 'N': return Keyboard::N; + case '0': return Keyboard::Num0; + case '1': return Keyboard::Num1; + case '2': return Keyboard::Num2; + case '3': return Keyboard::Num3; + case '4': return Keyboard::Num4; + case '5': return Keyboard::Num5; + case '6': return Keyboard::Num6; + case '7': return Keyboard::Num7; + case '8': return Keyboard::Num8; + case '9': return Keyboard::Num9; + } + + return Keyboard::Unknown; +} + + +//////////////////////////////////////////////////////////// +LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) +{ + // Associate handle and Window instance when the creation message is received + if (message == WM_CREATE) + { + // Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow) + LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams; + + // Set as the "user data" parameter of the window + SetWindowLongPtrW(handle, GWLP_USERDATA, window); + } + + // Get the WindowImpl instance corresponding to the window handle + WindowImplWin32* window = handle ? reinterpret_cast<WindowImplWin32*>(GetWindowLongPtr(handle, GWLP_USERDATA)) : NULL; + + // Forward the event to the appropriate function + if (window) + { + window->processEvent(message, wParam, lParam); + + if (window->m_callback) + return CallWindowProcW(reinterpret_cast<WNDPROC>(window->m_callback), handle, message, wParam, lParam); + } + + // We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window + if (message == WM_CLOSE) + return 0; + + // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus + if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU)) + return 0; + + return DefWindowProcW(handle, message, wParam, lParam); +} + +} // namespace priv + +} // namespace sf + diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index a0ccc61..0bb3ce8 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -1,248 +1,261 @@ -////////////////////////////////////////////////////////////
-//
-// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
-//
-// 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.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it freely,
-// subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented;
-// you must not claim that you wrote the original software.
-// If you use this software in a product, an acknowledgment
-// in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such,
-// and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-//
-////////////////////////////////////////////////////////////
-
-#ifndef SFML_WINDOWIMPLWIN32_HPP
-#define SFML_WINDOWIMPLWIN32_HPP
-
-////////////////////////////////////////////////////////////
-// Headers
-////////////////////////////////////////////////////////////
-#include <SFML/Window/Event.hpp>
-#include <SFML/Window/WindowImpl.hpp>
-#include <SFML/System/String.hpp>
-#include <windows.h>
-
-
-namespace sf
-{
-namespace priv
-{
-////////////////////////////////////////////////////////////
-/// \brief Windows implementation of WindowImpl
-///
-////////////////////////////////////////////////////////////
-class WindowImplWin32 : public WindowImpl
-{
-public :
-
- ////////////////////////////////////////////////////////////
- /// \brief Construct the window implementation from an existing control
- ///
- /// \param handle Platform-specific handle of the control
- ///
- ////////////////////////////////////////////////////////////
- WindowImplWin32(WindowHandle handle);
-
- ////////////////////////////////////////////////////////////
- /// \brief Create the window implementation
- ///
- /// \param mode Video mode to use
- /// \param title Title of the window
- /// \param style Window style
- /// \param settings Additional settings for the underlying OpenGL context
- ///
- ////////////////////////////////////////////////////////////
- WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings);
-
- ////////////////////////////////////////////////////////////
- /// \brief Destructor
- ///
- ////////////////////////////////////////////////////////////
- ~WindowImplWin32();
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the OS-specific handle of the window
- ///
- /// \return Handle of the window
- ///
- ////////////////////////////////////////////////////////////
- virtual WindowHandle getSystemHandle() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the position of the window
- ///
- /// \return Position of the window, in pixels
- ///
- ////////////////////////////////////////////////////////////
- virtual Vector2i getPosition() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Change the position of the window on screen
- ///
- /// \param position New position of the window, in pixels
- ///
- ////////////////////////////////////////////////////////////
- virtual void setPosition(const Vector2i& position);
-
- ////////////////////////////////////////////////////////////
- /// \brief Get the client size of the window
- ///
- /// \return Size of the window, in pixels
- ///
- ////////////////////////////////////////////////////////////
- virtual Vector2u getSize() const;
-
- ////////////////////////////////////////////////////////////
- /// \brief Change the size of the rendering region of the window
- ///
- /// \param size New size, in pixels
- ///
- ////////////////////////////////////////////////////////////
- virtual void setSize(const Vector2u& size);
-
- ////////////////////////////////////////////////////////////
- /// \brief Change the title of the window
- ///
- /// \param title New title
- ///
- ////////////////////////////////////////////////////////////
- virtual void setTitle(const String& title);
-
- ////////////////////////////////////////////////////////////
- /// \brief Change the window's icon
- ///
- /// \param width Icon's width, in pixels
- /// \param height Icon's height, in pixels
- /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits
- ///
- ////////////////////////////////////////////////////////////
- virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels);
-
- ////////////////////////////////////////////////////////////
- /// \brief Show or hide the window
- ///
- /// \param visible True to show, false to hide
- ///
- ////////////////////////////////////////////////////////////
- virtual void setVisible(bool visible);
-
- ////////////////////////////////////////////////////////////
- /// \brief Show or hide the mouse cursor
- ///
- /// \param visible True to show, false to hide
- ///
- ////////////////////////////////////////////////////////////
- virtual void setMouseCursorVisible(bool visible);
-
- ////////////////////////////////////////////////////////////
- /// \brief Enable or disable automatic key-repeat
- ///
- /// \param enabled True to enable, false to disable
- ///
- ////////////////////////////////////////////////////////////
- virtual void setKeyRepeatEnabled(bool enabled);
-
-protected:
-
- ////////////////////////////////////////////////////////////
- /// \brief Process incoming events from the operating system
- ///
- ////////////////////////////////////////////////////////////
- virtual void processEvents();
-
-private :
-
- ////////////////////////////////////////////////////////////
- /// Register the window class
- ///
- ////////////////////////////////////////////////////////////
- void registerWindowClass();
-
- ////////////////////////////////////////////////////////////
- /// \brief Switch to fullscreen mode
- ///
- /// \param mode Video mode to switch to
- ///
- ////////////////////////////////////////////////////////////
- void switchToFullscreen(const VideoMode& mode);
-
- ////////////////////////////////////////////////////////////
- /// \brief Free all the graphical resources attached to the window
- ///
- ////////////////////////////////////////////////////////////
- void cleanup();
-
- ////////////////////////////////////////////////////////////
- /// \brief Process a Win32 event
- ///
- /// \param message Message to process
- /// \param wParam First parameter of the event
- /// \param lParam Second parameter of the event
- ///
- ////////////////////////////////////////////////////////////
- void processEvent(UINT message, WPARAM wParam, LPARAM lParam);
-
- ////////////////////////////////////////////////////////////
- /// \brief Convert a Win32 virtual key code to a SFML key code
- ///
- /// \param key Virtual key code to convert
- /// \param flags Additional flags
- ///
- /// \return SFML key code corresponding to the key
- ///
- ////////////////////////////////////////////////////////////
- static Keyboard::Key virtualKeyCodeToSF(WPARAM key, LPARAM flags);
-
- ////////////////////////////////////////////////////////////
- /// \brief Check if the current version of the OS supports
- /// unicode messages and functions ; Windows 95/98/Me
- /// may not support it, whereas Windows NT/2000/XP/Vista
- /// will
- ///
- /// \return True if the OS supports unicode
- ///
- ////////////////////////////////////////////////////////////
- static bool hasUnicodeSupport();
-
- ////////////////////////////////////////////////////////////
- /// \brief Function called whenever one of our windows receives a message
- ///
- /// \param handle Win32 handle of the window
- /// \param message Message received
- /// \param wParam First parameter of the message
- /// \param lParam Second parameter of the message
- ///
- /// \return True to discard the event after it has been processed
- ///
- ////////////////////////////////////////////////////////////
- static LRESULT CALLBACK globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam);
-
- ////////////////////////////////////////////////////////////
- // Member data
- ////////////////////////////////////////////////////////////
- HWND m_handle; ///< Win32 handle of the window
- LONG_PTR m_callback; ///< Stores the original event callback function of the control
- HCURSOR m_cursor; ///< The system cursor to display into the window
- HICON m_icon; ///< Custom icon assigned to the window
- bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
- Vector2u m_lastSize; ///< The last handled size of the window
- bool m_resizing; ///< Is the window being resized ?
- Uint16 m_surrogate; ///< First half of the surrogate pair, in case we're receiving a Unicode character in two events
-};
-
-} // namespace priv
-
-} // namespace sf
-
-#endif // SFML_WINDOWIMPLWIN32_HPP
+//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_WINDOWIMPLWIN32_HPP +#define SFML_WINDOWIMPLWIN32_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include <SFML/Window/Event.hpp> +#include <SFML/Window/WindowImpl.hpp> +#include <SFML/System/String.hpp> +#include <windows.h> + + +namespace sf +{ +namespace priv +{ +//////////////////////////////////////////////////////////// +/// \brief Windows implementation of WindowImpl +/// +//////////////////////////////////////////////////////////// +class WindowImplWin32 : public WindowImpl +{ +public: + + //////////////////////////////////////////////////////////// + /// \brief Construct the window implementation from an existing control + /// + /// \param handle Platform-specific handle of the control + /// + //////////////////////////////////////////////////////////// + WindowImplWin32(WindowHandle handle); + + //////////////////////////////////////////////////////////// + /// \brief Create the window implementation + /// + /// \param mode Video mode to use + /// \param title Title of the window + /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context + /// + //////////////////////////////////////////////////////////// + WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); + + //////////////////////////////////////////////////////////// + /// \brief Destructor + /// + //////////////////////////////////////////////////////////// + ~WindowImplWin32(); + + //////////////////////////////////////////////////////////// + /// \brief Get the OS-specific handle of the window + /// + /// \return Handle of the window + /// + //////////////////////////////////////////////////////////// + virtual WindowHandle getSystemHandle() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the window + /// + /// \return Position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2i getPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the position of the window on screen + /// + /// \param position New position of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setPosition(const Vector2i& position); + + //////////////////////////////////////////////////////////// + /// \brief Get the client size of the window + /// + /// \return Size of the window, in pixels + /// + //////////////////////////////////////////////////////////// + virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the size of the rendering region of the window + /// + /// \param size New size, in pixels + /// + //////////////////////////////////////////////////////////// + virtual void setSize(const Vector2u& size); + + //////////////////////////////////////////////////////////// + /// \brief Change the title of the window + /// + /// \param title New title + /// + //////////////////////////////////////////////////////////// + virtual void setTitle(const String& title); + + //////////////////////////////////////////////////////////// + /// \brief Change the window's icon + /// + /// \param width Icon's width, in pixels + /// \param height Icon's height, in pixels + /// \param pixels Pointer to the pixels in memory, format must be RGBA 32 bits + /// + //////////////////////////////////////////////////////////// + virtual void setIcon(unsigned int width, unsigned int height, const Uint8* pixels); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the window + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Show or hide the mouse cursor + /// + /// \param visible True to show, false to hide + /// + //////////////////////////////////////////////////////////// + virtual void setMouseCursorVisible(bool visible); + + //////////////////////////////////////////////////////////// + /// \brief Enable or disable automatic key-repeat + /// + /// \param enabled True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + virtual void setKeyRepeatEnabled(bool enabled); + + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + //////////////////////////////////////////////////////////// + virtual void requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Check whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + +protected: + + //////////////////////////////////////////////////////////// + /// \brief Process incoming events from the operating system + /// + //////////////////////////////////////////////////////////// + virtual void processEvents(); + +private: + + //////////////////////////////////////////////////////////// + /// Register the window class + /// + //////////////////////////////////////////////////////////// + void registerWindowClass(); + + //////////////////////////////////////////////////////////// + /// \brief Switch to fullscreen mode + /// + /// \param mode Video mode to switch to + /// + //////////////////////////////////////////////////////////// + void switchToFullscreen(const VideoMode& mode); + + //////////////////////////////////////////////////////////// + /// \brief Free all the graphical resources attached to the window + /// + //////////////////////////////////////////////////////////// + void cleanup(); + + //////////////////////////////////////////////////////////// + /// \brief Process a Win32 event + /// + /// \param message Message to process + /// \param wParam First parameter of the event + /// \param lParam Second parameter of the event + /// + //////////////////////////////////////////////////////////// + void processEvent(UINT message, WPARAM wParam, LPARAM lParam); + + //////////////////////////////////////////////////////////// + /// \brief Enables or disables tracking for the mouse cursor leaving the window + /// + /// \param track True to enable, false to disable + /// + //////////////////////////////////////////////////////////// + void setTracking(bool track); + + //////////////////////////////////////////////////////////// + /// \brief Convert a Win32 virtual key code to a SFML key code + /// + /// \param key Virtual key code to convert + /// \param flags Additional flags + /// + /// \return SFML key code corresponding to the key + /// + //////////////////////////////////////////////////////////// + static Keyboard::Key virtualKeyCodeToSF(WPARAM key, LPARAM flags); + + //////////////////////////////////////////////////////////// + /// \brief Function called whenever one of our windows receives a message + /// + /// \param handle Win32 handle of the window + /// \param message Message received + /// \param wParam First parameter of the message + /// \param lParam Second parameter of the message + /// + /// \return True to discard the event after it has been processed + /// + //////////////////////////////////////////////////////////// + static LRESULT CALLBACK globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + HWND m_handle; ///< Win32 handle of the window + LONG_PTR m_callback; ///< Stores the original event callback function of the control + HCURSOR m_cursor; ///< The system cursor to display into the window + HICON m_icon; ///< Custom icon assigned to the window + bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events + Vector2u m_lastSize; ///< The last handled size of the window + bool m_resizing; ///< Is the window being resized? + Uint16 m_surrogate; ///< First half of the surrogate pair, in case we're receiving a Unicode character in two events + bool m_mouseInside; ///< Mouse is inside the window? +}; + +} // namespace priv + +} // namespace sf + +#endif // SFML_WINDOWIMPLWIN32_HPP |