mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Merge branch '2.3.x'
This commit is contained in:
commit
26fc872844
@ -40,7 +40,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake)
|
|||||||
# setup version numbers
|
# setup version numbers
|
||||||
set(VERSION_MAJOR 2)
|
set(VERSION_MAJOR 2)
|
||||||
set(VERSION_MINOR 3)
|
set(VERSION_MINOR 3)
|
||||||
set(VERSION_PATCH 0)
|
set(VERSION_PATCH 1)
|
||||||
|
|
||||||
# add the SFML header path
|
# add the SFML header path
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
@ -1,3 +1,39 @@
|
|||||||
|
SFML 2.3.1
|
||||||
|
==========
|
||||||
|
|
||||||
|
Also available on the website: http://www.sfml-dev.org/changelog.php#sfml-2.3.1
|
||||||
|
|
||||||
|
Window
|
||||||
|
======
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
* [Android] Make sure a window still exists before trying to access its dimensions (#854)
|
||||||
|
* [Android] Added Android API level checks (#856)
|
||||||
|
* [Android] Updated the JNI/event handling code (#906)
|
||||||
|
* [Linux] Resized events are only spawned when the window size actually changes (#878, #893)
|
||||||
|
* [Linux] Whitelisted X SHAPE events (#879, #883)
|
||||||
|
* [Linux] Remap Unix keyboard when user changes layout (#895, #897)
|
||||||
|
* [Linux] Fix undefined behavior in ewmhSupported() (#892, #901)
|
||||||
|
|
||||||
|
|
||||||
|
Graphics
|
||||||
|
========
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
* Added support for GL_EXT_texture_edge_clamp for systems that don't expose GL_SGIS_texture_edge_clamp (#880, #882)
|
||||||
|
|
||||||
|
|
||||||
|
Audio
|
||||||
|
=====
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
* [Android] Fixed audio files not loading (and possibly crashing) (#855, #887)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SFML 2.3
|
SFML 2.3
|
||||||
========
|
========
|
||||||
|
|
||||||
|
@ -69,6 +69,10 @@ public:
|
|||||||
/// See the documentation of sf::InputSoundFile for the list
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
/// of supported formats.
|
/// of supported formats.
|
||||||
///
|
///
|
||||||
|
/// \warning Since the music is not loaded at once but rather
|
||||||
|
/// streamed continuously, the file must remain accessible until
|
||||||
|
/// the sf::Music object loads a new music or is destroyed.
|
||||||
|
///
|
||||||
/// \param filename Path of the music file to open
|
/// \param filename Path of the music file to open
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if loading succeeded, false if it failed
|
||||||
@ -85,10 +89,11 @@ public:
|
|||||||
/// to do so).
|
/// to do so).
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
/// of supported formats.
|
/// of supported formats.
|
||||||
/// Since the music is not loaded completely but rather streamed
|
///
|
||||||
/// continuously, the \a data must remain available as long as the
|
/// \warning Since the music is not loaded at once but rather streamed
|
||||||
/// music is playing (i.e. you can't deallocate it right after calling
|
/// continuously, the \a data buffer must remain accessible until
|
||||||
/// this function).
|
/// the sf::Music object loads a new music or is destroyed. That is,
|
||||||
|
/// you can't deallocate the buffer right after calling this function.
|
||||||
///
|
///
|
||||||
/// \param data Pointer to the file data in memory
|
/// \param data Pointer to the file data in memory
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
@ -107,10 +112,10 @@ public:
|
|||||||
/// to do so).
|
/// to do so).
|
||||||
/// See the documentation of sf::InputSoundFile for the list
|
/// See the documentation of sf::InputSoundFile for the list
|
||||||
/// of supported formats.
|
/// of supported formats.
|
||||||
/// Since the music is not loaded completely but rather streamed
|
///
|
||||||
/// continuously, the \a stream must remain alive as long as the
|
/// \warning Since the music is not loaded at once but rather
|
||||||
/// music is playing (i.e. you can't destroy it right after calling
|
/// streamed continuously, the \a stream must remain accessible
|
||||||
/// this function).
|
/// until the sf::Music object loads a new music or is destroyed.
|
||||||
///
|
///
|
||||||
/// \param stream Source stream to read from
|
/// \param stream Source stream to read from
|
||||||
///
|
///
|
||||||
@ -184,6 +189,9 @@ private:
|
|||||||
/// musics that usually take hundreds of MB when they are
|
/// musics that usually take hundreds of MB when they are
|
||||||
/// uncompressed: by streaming it instead of loading it entirely,
|
/// uncompressed: by streaming it instead of loading it entirely,
|
||||||
/// you avoid saturating the memory and have almost no loading delay.
|
/// you avoid saturating the memory and have almost no loading delay.
|
||||||
|
/// This implies that the underlying resource (file, stream or
|
||||||
|
/// memory buffer) must remain valid for the lifetime of the
|
||||||
|
/// sf::Music object.
|
||||||
///
|
///
|
||||||
/// Apart from that, a sf::Music has almost the same features as
|
/// Apart from that, a sf::Music has almost the same features as
|
||||||
/// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop
|
/// the sf::SoundBuffer / sf::Sound pair: you can play/pause/stop
|
||||||
|
@ -183,7 +183,7 @@ protected:
|
|||||||
/// \param interval Processing interval
|
/// \param interval Processing interval
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setProcessingInterval(sf::Time interval);
|
void setProcessingInterval(Time interval);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Start capturing audio data
|
/// \brief Start capturing audio data
|
||||||
@ -260,7 +260,7 @@ private:
|
|||||||
Thread m_thread; ///< Thread running the background recording task
|
Thread m_thread; ///< Thread running the background recording task
|
||||||
std::vector<Int16> m_samples; ///< Buffer to store captured samples
|
std::vector<Int16> m_samples; ///< Buffer to store captured samples
|
||||||
unsigned int m_sampleRate; ///< Sample rate
|
unsigned int m_sampleRate; ///< Sample rate
|
||||||
sf::Time m_processingInterval; ///< Time period between calls to onProcessSamples
|
Time m_processingInterval; ///< Time period between calls to onProcessSamples
|
||||||
bool m_isCapturing; ///< Capturing state
|
bool m_isCapturing; ///< Capturing state
|
||||||
std::string m_deviceName; ///< Name of the audio capture device
|
std::string m_deviceName; ///< Name of the audio capture device
|
||||||
};
|
};
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#define SFML_VERSION_MAJOR 2
|
#define SFML_VERSION_MAJOR 2
|
||||||
#define SFML_VERSION_MINOR 3
|
#define SFML_VERSION_MINOR 3
|
||||||
#define SFML_VERSION_PATCH 0
|
#define SFML_VERSION_PATCH 1
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -95,6 +95,10 @@ public:
|
|||||||
/// fonts installed on the user's system, thus you can't
|
/// fonts installed on the user's system, thus you can't
|
||||||
/// load them directly.
|
/// load them directly.
|
||||||
///
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
|
/// function, so the file has to remain accessible until
|
||||||
|
/// the sf::Font object loads a new font or is destroyed.
|
||||||
|
///
|
||||||
/// \param filename Path of the font file to load
|
/// \param filename Path of the font file to load
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if loading succeeded, false if it failed
|
||||||
@ -109,9 +113,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||||
/// Warning: SFML cannot preload all the font data in this
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
/// function, so the buffer pointed by \a data has to remain
|
/// function, so the buffer pointed by \a data has to remain
|
||||||
/// valid as long as the font is used.
|
/// valid until the sf::Font object loads a new font or
|
||||||
|
/// is destroyed.
|
||||||
///
|
///
|
||||||
/// \param data Pointer to the file data in memory
|
/// \param data Pointer to the file data in memory
|
||||||
/// \param sizeInBytes Size of the data to load, in bytes
|
/// \param sizeInBytes Size of the data to load, in bytes
|
||||||
@ -132,6 +138,10 @@ public:
|
|||||||
/// function, so the contents of \a stream have to remain
|
/// function, so the contents of \a stream have to remain
|
||||||
/// valid as long as the font is used.
|
/// valid as long as the font is used.
|
||||||
///
|
///
|
||||||
|
/// \warning SFML cannot preload all the font data in this
|
||||||
|
/// function, so the stream has to remain accessible until
|
||||||
|
/// the sf::Font object loads a new font or is destroyed.
|
||||||
|
///
|
||||||
/// \param stream Source stream to read from
|
/// \param stream Source stream to read from
|
||||||
///
|
///
|
||||||
/// \return True if loading succeeded, false if it failed
|
/// \return True if loading succeeded, false if it failed
|
||||||
@ -278,7 +288,7 @@ private:
|
|||||||
Page();
|
Page();
|
||||||
|
|
||||||
GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph
|
GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph
|
||||||
sf::Texture texture; ///< Texture containing the pixels of the glyphs
|
Texture texture; ///< Texture containing the pixels of the glyphs
|
||||||
unsigned int nextRow; ///< Y position of the next new row in the texture
|
unsigned int nextRow; ///< Y position of the next new row in the texture
|
||||||
std::vector<Row> rows; ///< List containing the position of all the existing rows
|
std::vector<Row> rows; ///< List containing the position of all the existing rows
|
||||||
};
|
};
|
||||||
|
@ -150,7 +150,7 @@ public:
|
|||||||
/// directly without defining render states explicitly -- the
|
/// directly without defining render states explicitly -- the
|
||||||
/// default set of states is ok in most cases.
|
/// default set of states is ok in most cases.
|
||||||
/// \code
|
/// \code
|
||||||
/// window.Draw(sprite);
|
/// window.draw(sprite);
|
||||||
/// \endcode
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// If you want to use a single specific render state,
|
/// If you want to use a single specific render state,
|
||||||
|
@ -399,7 +399,7 @@ public:
|
|||||||
/// \param transform Transform to assign
|
/// \param transform Transform to assign
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setParameter(const std::string& name, const sf::Transform& transform);
|
void setParameter(const std::string& name, const Transform& transform);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Change a texture parameter of the shader
|
/// \brief Change a texture parameter of the shader
|
||||||
|
@ -187,7 +187,7 @@ public:
|
|||||||
/// \see loadFromFile, loadFromMemory, loadFromImage
|
/// \see loadFromFile, loadFromMemory, loadFromImage
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool loadFromStream(sf::InputStream& stream, const IntRect& area = IntRect());
|
bool loadFromStream(InputStream& stream, const IntRect& area = IntRect());
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Load the texture from an image
|
/// \brief Load the texture from an image
|
||||||
|
@ -123,7 +123,7 @@ private:
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
sf::priv::ResourceStream *m_file;
|
priv::ResourceStream* m_file;
|
||||||
#else
|
#else
|
||||||
std::FILE* m_file; ///< stdio file stream
|
std::FILE* m_file; ///< stdio file stream
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
{
|
{
|
||||||
Identification();
|
Identification();
|
||||||
|
|
||||||
sf::String name; ///< Name of the joystick
|
String name; ///< Name of the joystick
|
||||||
unsigned int vendorId; ///< Manufacturer identifier
|
unsigned int vendorId; ///< Manufacturer identifier
|
||||||
unsigned int productId; ///< Product identifier
|
unsigned int productId; ///< Product identifier
|
||||||
};
|
};
|
||||||
|
@ -65,10 +65,7 @@ bool InputSoundFile::openFromFile(const std::string& filename)
|
|||||||
// Find a suitable reader for the file type
|
// Find a suitable reader for the file type
|
||||||
m_reader = SoundFileFactory::createReaderFromFilename(filename);
|
m_reader = SoundFileFactory::createReaderFromFilename(filename);
|
||||||
if (!m_reader)
|
if (!m_reader)
|
||||||
{
|
|
||||||
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap the file into a stream
|
// Wrap the file into a stream
|
||||||
FileInputStream* file = new FileInputStream;
|
FileInputStream* file = new FileInputStream;
|
||||||
@ -108,10 +105,7 @@ bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
// Find a suitable reader for the file type
|
// Find a suitable reader for the file type
|
||||||
m_reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes);
|
m_reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes);
|
||||||
if (!m_reader)
|
if (!m_reader)
|
||||||
{
|
|
||||||
err() << "Failed to open sound file from memory (format not supported)" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap the memory file into a stream
|
// Wrap the memory file into a stream
|
||||||
MemoryInputStream* memory = new MemoryInputStream;
|
MemoryInputStream* memory = new MemoryInputStream;
|
||||||
@ -147,10 +141,7 @@ bool InputSoundFile::openFromStream(InputStream& stream)
|
|||||||
// Find a suitable reader for the file type
|
// Find a suitable reader for the file type
|
||||||
m_reader = SoundFileFactory::createReaderFromStream(stream);
|
m_reader = SoundFileFactory::createReaderFromStream(stream);
|
||||||
if (!m_reader)
|
if (!m_reader)
|
||||||
{
|
|
||||||
err() << "Failed to open sound file from stream (format not supported)" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// store the stream
|
// store the stream
|
||||||
m_stream = &stream;
|
m_stream = &stream;
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <SFML/Audio/OutputSoundFile.hpp>
|
#include <SFML/Audio/OutputSoundFile.hpp>
|
||||||
#include <SFML/Audio/SoundFileWriter.hpp>
|
#include <SFML/Audio/SoundFileWriter.hpp>
|
||||||
#include <SFML/Audio/SoundFileFactory.hpp>
|
#include <SFML/Audio/SoundFileFactory.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -57,10 +56,7 @@ bool OutputSoundFile::openFromFile(const std::string& filename, unsigned int sam
|
|||||||
// Find a suitable writer for the file type
|
// Find a suitable writer for the file type
|
||||||
m_writer = SoundFileFactory::createWriterFromFilename(filename);
|
m_writer = SoundFileFactory::createWriterFromFilename(filename);
|
||||||
if (!m_writer)
|
if (!m_writer)
|
||||||
{
|
|
||||||
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the stream to the reader
|
// Pass the stream to the reader
|
||||||
if (!m_writer->open(filename, sampleRate, channelCount))
|
if (!m_writer->open(filename, sampleRate, channelCount))
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <SFML/Audio/SoundFileWriterWav.hpp>
|
#include <SFML/Audio/SoundFileWriterWav.hpp>
|
||||||
#include <SFML/System/FileInputStream.hpp>
|
#include <SFML/System/FileInputStream.hpp>
|
||||||
#include <SFML/System/MemoryInputStream.hpp>
|
#include <SFML/System/MemoryInputStream.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -69,8 +70,10 @@ SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& f
|
|||||||
|
|
||||||
// Wrap the input file into a file stream
|
// Wrap the input file into a file stream
|
||||||
FileInputStream stream;
|
FileInputStream stream;
|
||||||
if (!stream.open(filename))
|
if (!stream.open(filename)) {
|
||||||
|
err() << "Failed to open sound file \"" << filename << "\" (couldn't open stream)" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Test the filename in all the registered factories
|
// Test the filename in all the registered factories
|
||||||
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
|
for (ReaderFactoryArray::const_iterator it = s_readers.begin(); it != s_readers.end(); ++it)
|
||||||
@ -81,6 +84,7 @@ SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No suitable reader found
|
// No suitable reader found
|
||||||
|
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +108,7 @@ SoundFileReader* SoundFileFactory::createReaderFromMemory(const void* data, std:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No suitable reader found
|
// No suitable reader found
|
||||||
|
err() << "Failed to open sound file from memory (format not supported)" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +128,7 @@ SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No suitable reader found
|
// No suitable reader found
|
||||||
|
err() << "Failed to open sound file from stream (format not supported)" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +147,7 @@ SoundFileWriter* SoundFileFactory::createWriterFromFilename(const std::string& f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No suitable writer found
|
// No suitable writer found
|
||||||
|
err() << "Failed to open sound file \"" << filename << "\" (format not supported)" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ std::vector<std::string> SoundRecorder::getAvailableDevices()
|
|||||||
{
|
{
|
||||||
std::vector<std::string> deviceNameList;
|
std::vector<std::string> deviceNameList;
|
||||||
|
|
||||||
const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
const ALchar* deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
if (deviceList)
|
if (deviceList)
|
||||||
{
|
{
|
||||||
while (*deviceList)
|
while (*deviceList)
|
||||||
@ -210,7 +210,7 @@ bool SoundRecorder::isAvailable()
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundRecorder::setProcessingInterval(sf::Time interval)
|
void SoundRecorder::setProcessingInterval(Time interval)
|
||||||
{
|
{
|
||||||
m_processingInterval = interval;
|
m_processingInterval = interval;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
// Core since 1.0
|
// Core since 1.0
|
||||||
#define GLEXT_multitexture true
|
#define GLEXT_multitexture true
|
||||||
#define GLEXT_texture_edge_clamp true
|
#define GLEXT_texture_edge_clamp true
|
||||||
|
#define GLEXT_EXT_texture_edge_clamp true
|
||||||
#define GLEXT_blend_minmax true
|
#define GLEXT_blend_minmax true
|
||||||
#define GLEXT_glClientActiveTexture glClientActiveTexture
|
#define GLEXT_glClientActiveTexture glClientActiveTexture
|
||||||
#define GLEXT_glActiveTexture glActiveTexture
|
#define GLEXT_glActiveTexture glActiveTexture
|
||||||
@ -130,6 +131,9 @@
|
|||||||
#define GLEXT_texture_edge_clamp sfogl_ext_SGIS_texture_edge_clamp
|
#define GLEXT_texture_edge_clamp sfogl_ext_SGIS_texture_edge_clamp
|
||||||
#define GLEXT_GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE_SGIS
|
#define GLEXT_GL_CLAMP_TO_EDGE GL_CLAMP_TO_EDGE_SGIS
|
||||||
|
|
||||||
|
// Core since 1.2 - EXT_texture_edge_clamp
|
||||||
|
#define GLEXT_EXT_texture_edge_clamp sfogl_ext_EXT_texture_edge_clamp
|
||||||
|
|
||||||
// Core since 1.2 - EXT_blend_minmax
|
// Core since 1.2 - EXT_blend_minmax
|
||||||
#define GLEXT_blend_minmax sfogl_ext_EXT_blend_minmax
|
#define GLEXT_blend_minmax sfogl_ext_EXT_blend_minmax
|
||||||
#define GLEXT_glBlendEquation glBlendEquationEXT
|
#define GLEXT_glBlendEquation glBlendEquationEXT
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
// lua LoadGen.lua -style=pointer_c -spec=gl -version=1.1 -indent=space -prefix=sf -extfile=GLExtensions.txt GLLoader
|
// lua LoadGen.lua -style=pointer_c -spec=gl -version=1.1 -indent=space -prefix=sf -extfile=GLExtensions.txt GLLoader
|
||||||
|
|
||||||
SGIS_texture_edge_clamp
|
SGIS_texture_edge_clamp
|
||||||
|
//EXT_texture_edge_clamp
|
||||||
EXT_blend_minmax
|
EXT_blend_minmax
|
||||||
EXT_blend_subtract
|
EXT_blend_subtract
|
||||||
ARB_multitexture
|
ARB_multitexture
|
||||||
|
@ -50,6 +50,7 @@ static sf::GlFunctionPointer IntGetProcAddress(const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED;
|
int sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED;
|
||||||
|
int sfogl_ext_EXT_texture_edge_clamp = sfogl_LOAD_FAILED;
|
||||||
int sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
|
int sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
|
||||||
int sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
|
int sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
|
||||||
int sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
|
int sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
|
||||||
@ -317,8 +318,9 @@ typedef struct sfogl_StrToExtMap_s
|
|||||||
PFN_LOADFUNCPOINTERS LoadExtension;
|
PFN_LOADFUNCPOINTERS LoadExtension;
|
||||||
} sfogl_StrToExtMap;
|
} sfogl_StrToExtMap;
|
||||||
|
|
||||||
static sfogl_StrToExtMap ExtensionMap[12] = {
|
static sfogl_StrToExtMap ExtensionMap[13] = {
|
||||||
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
|
{"GL_SGIS_texture_edge_clamp", &sfogl_ext_SGIS_texture_edge_clamp, NULL},
|
||||||
|
{"GL_EXT_texture_edge_clamp", &sfogl_ext_EXT_texture_edge_clamp, NULL},
|
||||||
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
|
{"GL_EXT_blend_minmax", &sfogl_ext_EXT_blend_minmax, Load_EXT_blend_minmax},
|
||||||
{"GL_EXT_blend_subtract", &sfogl_ext_EXT_blend_subtract, NULL},
|
{"GL_EXT_blend_subtract", &sfogl_ext_EXT_blend_subtract, NULL},
|
||||||
{"GL_ARB_multitexture", &sfogl_ext_ARB_multitexture, Load_ARB_multitexture},
|
{"GL_ARB_multitexture", &sfogl_ext_ARB_multitexture, Load_ARB_multitexture},
|
||||||
@ -332,7 +334,7 @@ static sfogl_StrToExtMap ExtensionMap[12] = {
|
|||||||
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object}
|
{"GL_EXT_framebuffer_object", &sfogl_ext_EXT_framebuffer_object, Load_EXT_framebuffer_object}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int g_extensionMapSize = 12;
|
static int g_extensionMapSize = 13;
|
||||||
|
|
||||||
static sfogl_StrToExtMap *FindExtEntry(const char *extensionName)
|
static sfogl_StrToExtMap *FindExtEntry(const char *extensionName)
|
||||||
{
|
{
|
||||||
@ -350,6 +352,7 @@ static sfogl_StrToExtMap *FindExtEntry(const char *extensionName)
|
|||||||
static void ClearExtensionVars()
|
static void ClearExtensionVars()
|
||||||
{
|
{
|
||||||
sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED;
|
sfogl_ext_SGIS_texture_edge_clamp = sfogl_LOAD_FAILED;
|
||||||
|
sfogl_ext_EXT_texture_edge_clamp = sfogl_LOAD_FAILED;
|
||||||
sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
|
sfogl_ext_EXT_blend_minmax = sfogl_LOAD_FAILED;
|
||||||
sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
|
sfogl_ext_EXT_blend_subtract = sfogl_LOAD_FAILED;
|
||||||
sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
|
sfogl_ext_ARB_multitexture = sfogl_LOAD_FAILED;
|
||||||
|
@ -174,6 +174,7 @@ extern "C" {
|
|||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
extern int sfogl_ext_SGIS_texture_edge_clamp;
|
extern int sfogl_ext_SGIS_texture_edge_clamp;
|
||||||
|
extern int sfogl_ext_EXT_texture_edge_clamp;
|
||||||
extern int sfogl_ext_EXT_blend_minmax;
|
extern int sfogl_ext_EXT_blend_minmax;
|
||||||
extern int sfogl_ext_EXT_blend_subtract;
|
extern int sfogl_ext_EXT_blend_subtract;
|
||||||
extern int sfogl_ext_ARB_multitexture;
|
extern int sfogl_ext_ARB_multitexture;
|
||||||
@ -188,6 +189,8 @@ extern int sfogl_ext_EXT_framebuffer_object;
|
|||||||
|
|
||||||
#define GL_CLAMP_TO_EDGE_SGIS 0x812F
|
#define GL_CLAMP_TO_EDGE_SGIS 0x812F
|
||||||
|
|
||||||
|
#define GL_CLAMP_TO_EDGE_EXT 0x812F
|
||||||
|
|
||||||
#define GL_BLEND_EQUATION_EXT 0x8009
|
#define GL_BLEND_EQUATION_EXT 0x8009
|
||||||
#define GL_FUNC_ADD_EXT 0x8006
|
#define GL_FUNC_ADD_EXT 0x8006
|
||||||
#define GL_MAX_EXT 0x8008
|
#define GL_MAX_EXT 0x8008
|
||||||
|
@ -385,7 +385,7 @@ void Shader::setParameter(const std::string& name, const Color& color)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setParameter(const std::string& name, const sf::Transform& transform)
|
void Shader::setParameter(const std::string& name, const Transform& transform)
|
||||||
{
|
{
|
||||||
if (m_shaderProgram)
|
if (m_shaderProgram)
|
||||||
{
|
{
|
||||||
@ -768,7 +768,7 @@ void Shader::setParameter(const std::string& name, const Color& color)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Shader::setParameter(const std::string& name, const sf::Transform& transform)
|
void Shader::setParameter(const std::string& name, const Transform& transform)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ void Shape::setTexture(const Texture* texture, bool resetRect)
|
|||||||
if (texture)
|
if (texture)
|
||||||
{
|
{
|
||||||
// Recompute the texture area if requested, or if there was no texture & rect before
|
// Recompute the texture area if requested, or if there was no texture & rect before
|
||||||
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
|
if (resetRect || (!m_texture && (m_textureRect == IntRect())))
|
||||||
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
|
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,9 @@ bool Texture::create(unsigned int width, unsigned int height)
|
|||||||
// Make sure that the current texture binding will be preserved
|
// Make sure that the current texture binding will be preserved
|
||||||
priv::TextureSaver save;
|
priv::TextureSaver save;
|
||||||
|
|
||||||
if (!m_isRepeated && !GLEXT_texture_edge_clamp)
|
static bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_EXT_texture_edge_clamp;
|
||||||
|
|
||||||
|
if (!m_isRepeated && !textureEdgeClamp)
|
||||||
{
|
{
|
||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
|
|
||||||
@ -175,8 +177,8 @@ bool Texture::create(unsigned int width, unsigned int height)
|
|||||||
// Initialize the texture
|
// Initialize the texture
|
||||||
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
|
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
|
||||||
glCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_actualSize.x, m_actualSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
|
glCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_actualSize.x, m_actualSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST));
|
||||||
m_cacheId = getUniqueId();
|
m_cacheId = getUniqueId();
|
||||||
@ -480,7 +482,9 @@ void Texture::setRepeated(bool repeated)
|
|||||||
// Make sure that the current texture binding will be preserved
|
// Make sure that the current texture binding will be preserved
|
||||||
priv::TextureSaver save;
|
priv::TextureSaver save;
|
||||||
|
|
||||||
if (!m_isRepeated && !GLEXT_texture_edge_clamp)
|
static bool textureEdgeClamp = GLEXT_texture_edge_clamp || GLEXT_EXT_texture_edge_clamp;
|
||||||
|
|
||||||
|
if (!m_isRepeated && !textureEdgeClamp)
|
||||||
{
|
{
|
||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
|
|
||||||
@ -495,8 +499,8 @@ void Texture::setRepeated(bool repeated)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
|
glCheck(glBindTexture(GL_TEXTURE_2D, m_texture));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
||||||
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (textureEdgeClamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,27 @@ namespace sf
|
|||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
{
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
int getAndroidApiLevel(ANativeActivity* activity)
|
||||||
|
{
|
||||||
|
JNIEnv* lJNIEnv = activity->env;
|
||||||
|
|
||||||
|
jclass versionClass = lJNIEnv->FindClass("android/os/Build$VERSION");
|
||||||
|
if (versionClass == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
jfieldID sdkIntFieldID = lJNIEnv->GetStaticFieldID(versionClass, "SDK_INT", "I");
|
||||||
|
if (sdkIntFieldID == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
jint sdkInt = 0;
|
||||||
|
sdkInt = lJNIEnv->GetStaticIntField(versionClass, sdkIntFieldID);
|
||||||
|
|
||||||
|
return sdkInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
ActivityStates* retrieveStates(ANativeActivity* activity)
|
ActivityStates* retrieveStates(ANativeActivity* activity)
|
||||||
{
|
{
|
||||||
@ -117,6 +138,9 @@ void* main(ActivityStates* states)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void goToFullscreenMode(ANativeActivity* activity)
|
void goToFullscreenMode(ANativeActivity* activity)
|
||||||
{
|
{
|
||||||
|
// Get the current Android API level.
|
||||||
|
int apiLevel = sf::priv::getAndroidApiLevel(activity);
|
||||||
|
|
||||||
// Hide the status bar
|
// Hide the status bar
|
||||||
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN,
|
ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_FULLSCREEN,
|
||||||
AWINDOW_FLAG_FULLSCREEN);
|
AWINDOW_FLAG_FULLSCREEN);
|
||||||
@ -137,17 +161,35 @@ void goToFullscreenMode(ANativeActivity* activity)
|
|||||||
|
|
||||||
jclass classView = lJNIEnv->FindClass("android/view/View");
|
jclass classView = lJNIEnv->FindClass("android/view/View");
|
||||||
|
|
||||||
jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I");
|
// Default flags
|
||||||
jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE);
|
jint flags = 0;
|
||||||
|
|
||||||
|
// API Level 14
|
||||||
|
if (apiLevel >= 14)
|
||||||
|
{
|
||||||
|
jfieldID FieldSYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_LOW_PROFILE", "I");
|
||||||
|
jint SYSTEM_UI_FLAG_LOW_PROFILE = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_LOW_PROFILE);
|
||||||
|
flags |= SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||||
|
}
|
||||||
|
|
||||||
jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
|
// API Level 16
|
||||||
jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN);
|
if (apiLevel >= 16)
|
||||||
|
{
|
||||||
|
jfieldID FieldSYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
|
||||||
|
jint SYSTEM_UI_FLAG_FULLSCREEN = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_FULLSCREEN);
|
||||||
|
flags |= SYSTEM_UI_FLAG_FULLSCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
//jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");
|
// API Level 19
|
||||||
//jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
if (apiLevel >= 19)
|
||||||
|
{
|
||||||
|
jfieldID FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticFieldID(classView, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");
|
||||||
|
jint SYSTEM_UI_FLAG_IMMERSIVE_STICKY = lJNIEnv->GetStaticIntField(classView, FieldSYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||||
|
flags |= SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V");
|
jmethodID methodsetSystemUiVisibility = lJNIEnv->GetMethodID(classView, "setSystemUiVisibility", "(I)V");
|
||||||
lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN | 0x00001000);
|
lJNIEnv->CallVoidMethod(objectDecorView, methodsetSystemUiVisibility, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -386,13 +428,16 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
|
|||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
sf::Lock lock(states->mutex);
|
sf::Lock lock(states->mutex);
|
||||||
|
|
||||||
// Send an event to warn people about the window move/resize
|
// Make sure the window still exists before we access the dimensions on it
|
||||||
sf::Event event;
|
if (states->window != NULL) {
|
||||||
event.type = sf::Event::Resized;
|
// Send an event to warn people about the window move/resize
|
||||||
event.size.width = ANativeWindow_getWidth(states->window);
|
sf::Event event;
|
||||||
event.size.height = ANativeWindow_getHeight(states->window);
|
event.type = sf::Event::Resized;
|
||||||
|
event.size.width = ANativeWindow_getWidth(states->window);
|
||||||
|
event.size.height = ANativeWindow_getHeight(states->window);
|
||||||
|
|
||||||
states->forwardEvent(event);
|
states->forwardEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short
|
|||||||
{
|
{
|
||||||
// At this point the connection may have been either accepted or refused.
|
// At this point the connection may have been either accepted or refused.
|
||||||
// To know whether it's a success or a failure, we must check the address of the connected peer
|
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||||
if (getRemoteAddress() != sf::IpAddress::None)
|
if (getRemoteAddress() != IpAddress::None)
|
||||||
{
|
{
|
||||||
// Connection accepted
|
// Connection accepted
|
||||||
status = Done;
|
status = Done;
|
||||||
|
@ -63,7 +63,7 @@ Int64 ResourceStream::read(void *data, Int64 size)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Int64 ResourceStream::seek(Int64 position)
|
Int64 ResourceStream::seek(Int64 position)
|
||||||
{
|
{
|
||||||
AAsset_seek(m_file, position, SEEK_SET);
|
return AAsset_seek(m_file, position, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,8 @@ bool FileInputStream::open(const std::string& filename)
|
|||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
if (m_file)
|
if (m_file)
|
||||||
delete m_file;
|
delete m_file;
|
||||||
m_file = new sf::priv::ResourceStream(filename);
|
m_file = new priv::ResourceStream(filename);
|
||||||
|
return m_file->tell() != -1;
|
||||||
#else
|
#else
|
||||||
if (m_file)
|
if (m_file)
|
||||||
std::fclose(m_file);
|
std::fclose(m_file);
|
||||||
@ -127,9 +128,9 @@ Int64 FileInputStream::getSize()
|
|||||||
#else
|
#else
|
||||||
if (m_file)
|
if (m_file)
|
||||||
{
|
{
|
||||||
sf::Int64 position = tell();
|
Int64 position = tell();
|
||||||
std::fseek(m_file, 0, SEEK_END);
|
std::fseek(m_file, 0, SEEK_END);
|
||||||
sf::Int64 size = tell();
|
Int64 size = tell();
|
||||||
seek(position);
|
seek(position);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
|||||||
"INPUT_METHOD_SERVICE", "Ljava/lang/String;");
|
"INPUT_METHOD_SERVICE", "Ljava/lang/String;");
|
||||||
jobject INPUT_METHOD_SERVICE = lJNIEnv->GetStaticObjectField(ClassContext,
|
jobject INPUT_METHOD_SERVICE = lJNIEnv->GetStaticObjectField(ClassContext,
|
||||||
FieldINPUT_METHOD_SERVICE);
|
FieldINPUT_METHOD_SERVICE);
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassContext);
|
||||||
|
|
||||||
// Runs getSystemService(Context.INPUT_METHOD_SERVICE)
|
// Runs getSystemService(Context.INPUT_METHOD_SERVICE)
|
||||||
jclass ClassInputMethodManager =
|
jclass ClassInputMethodManager =
|
||||||
@ -86,6 +87,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
|||||||
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
|
"getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
|
||||||
jobject lInputMethodManager = lJNIEnv->CallObjectMethod(lNativeActivity,
|
jobject lInputMethodManager = lJNIEnv->CallObjectMethod(lNativeActivity,
|
||||||
MethodGetSystemService, INPUT_METHOD_SERVICE);
|
MethodGetSystemService, INPUT_METHOD_SERVICE);
|
||||||
|
lJNIEnv->DeleteLocalRef(INPUT_METHOD_SERVICE);
|
||||||
|
|
||||||
// Runs getWindow().getDecorView()
|
// Runs getWindow().getDecorView()
|
||||||
jmethodID MethodGetWindow = lJNIEnv->GetMethodID(ClassNativeActivity,
|
jmethodID MethodGetWindow = lJNIEnv->GetMethodID(ClassNativeActivity,
|
||||||
@ -95,6 +97,8 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
|||||||
jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(ClassWindow,
|
jmethodID MethodGetDecorView = lJNIEnv->GetMethodID(ClassWindow,
|
||||||
"getDecorView", "()Landroid/view/View;");
|
"getDecorView", "()Landroid/view/View;");
|
||||||
jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, MethodGetDecorView);
|
jobject lDecorView = lJNIEnv->CallObjectMethod(lWindow, MethodGetDecorView);
|
||||||
|
lJNIEnv->DeleteLocalRef(lWindow);
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassWindow);
|
||||||
|
|
||||||
if (visible)
|
if (visible)
|
||||||
{
|
{
|
||||||
@ -112,13 +116,19 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
|||||||
"getWindowToken", "()Landroid/os/IBinder;");
|
"getWindowToken", "()Landroid/os/IBinder;");
|
||||||
jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView,
|
jobject lBinder = lJNIEnv->CallObjectMethod(lDecorView,
|
||||||
MethodGetWindowToken);
|
MethodGetWindowToken);
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassView);
|
||||||
|
|
||||||
// lInputMethodManager.hideSoftInput(...)
|
// lInputMethodManager.hideSoftInput(...)
|
||||||
jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(ClassInputMethodManager,
|
jmethodID MethodHideSoftInput = lJNIEnv->GetMethodID(ClassInputMethodManager,
|
||||||
"hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
|
"hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
|
||||||
jboolean lRes = lJNIEnv->CallBooleanMethod(lInputMethodManager,
|
jboolean lRes = lJNIEnv->CallBooleanMethod(lInputMethodManager,
|
||||||
MethodHideSoftInput, lBinder, lFlags);
|
MethodHideSoftInput, lBinder, lFlags);
|
||||||
|
lJNIEnv->DeleteLocalRef(lBinder);
|
||||||
}
|
}
|
||||||
|
lJNIEnv->DeleteLocalRef(lNativeActivity);
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassNativeActivity);
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassInputMethodManager);
|
||||||
|
lJNIEnv->DeleteLocalRef(lDecorView);
|
||||||
|
|
||||||
// Finished with the JVM
|
// Finished with the JVM
|
||||||
lJavaVM->DetachCurrentThread();
|
lJavaVM->DetachCurrentThread();
|
||||||
|
@ -33,9 +33,11 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <android/looper.h>
|
#include <android/looper.h>
|
||||||
|
|
||||||
// Define missing constants
|
// Define missing constants for older API levels
|
||||||
#define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007
|
#if __ANDROID_API__ < 13
|
||||||
#define AMOTION_EVENT_ACTION_SCROLL 0x00000008
|
#define AMOTION_EVENT_ACTION_HOVER_MOVE 0x00000007
|
||||||
|
#define AMOTION_EVENT_ACTION_SCROLL 0x00000008
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Private data
|
// Private data
|
||||||
@ -232,7 +234,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
|
if (AInputQueue_preDispatchEvent(states->inputQueue, _event))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
int32_t handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
int32_t type = AInputEvent_getType(_event);
|
int32_t type = AInputEvent_getType(_event);
|
||||||
|
|
||||||
@ -244,8 +246,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) &&
|
if ((action == AKEY_EVENT_ACTION_DOWN || action == AKEY_EVENT_ACTION_UP || action == AKEY_EVENT_ACTION_MULTIPLE) &&
|
||||||
key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN)
|
key != AKEYCODE_VOLUME_UP && key != AKEYCODE_VOLUME_DOWN)
|
||||||
{
|
{
|
||||||
processKeyEvent(_event, states);
|
handled = processKeyEvent(_event, states);
|
||||||
handled = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == AINPUT_EVENT_TYPE_MOTION)
|
else if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||||
@ -256,16 +257,15 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
{
|
{
|
||||||
case AMOTION_EVENT_ACTION_SCROLL:
|
case AMOTION_EVENT_ACTION_SCROLL:
|
||||||
{
|
{
|
||||||
processScrollEvent(_event, states);
|
handled = processScrollEvent(_event, states);
|
||||||
handled = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
// todo: should hover_move indeed trigger the event?
|
||||||
|
// case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||||
case AMOTION_EVENT_ACTION_MOVE:
|
case AMOTION_EVENT_ACTION_MOVE:
|
||||||
{
|
{
|
||||||
processMotionEvent(_event, states);
|
handled = processMotionEvent(_event, states);
|
||||||
handled = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,8 +273,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||||
case AMOTION_EVENT_ACTION_DOWN:
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
{
|
{
|
||||||
processPointerEvent(true, _event, states);
|
handled = processPointerEvent(true, _event, states);
|
||||||
handled = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,8 +281,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
case AMOTION_EVENT_ACTION_UP:
|
case AMOTION_EVENT_ACTION_UP:
|
||||||
case AMOTION_EVENT_ACTION_CANCEL:
|
case AMOTION_EVENT_ACTION_CANCEL:
|
||||||
{
|
{
|
||||||
processPointerEvent(false, _event, states);
|
handled = processPointerEvent(false, _event, states);
|
||||||
handled = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +296,7 @@ int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states)
|
int WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates* states)
|
||||||
{
|
{
|
||||||
// Prepare the Java virtual machine
|
// Prepare the Java virtual machine
|
||||||
jint lResult;
|
jint lResult;
|
||||||
@ -314,8 +312,10 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
|||||||
|
|
||||||
lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
|
lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
|
||||||
|
|
||||||
if (lResult == JNI_ERR)
|
if (lResult == JNI_ERR) {
|
||||||
err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl;
|
err() << "Failed to initialize JNI, couldn't get the Unicode value" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve everything we need to create this MotionEvent in Java
|
// Retrieve everything we need to create this MotionEvent in Java
|
||||||
jlong downTime = AMotionEvent_getDownTime(_event);
|
jlong downTime = AMotionEvent_getDownTime(_event);
|
||||||
@ -340,6 +340,9 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
|||||||
jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F");
|
jmethodID MethodGetAxisValue = lJNIEnv->GetMethodID(ClassMotionEvent, "getAxisValue", "(I)F");
|
||||||
jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001);
|
jfloat delta = lJNIEnv->CallFloatMethod(ObjectMotionEvent, MethodGetAxisValue, 0x00000001);
|
||||||
|
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassMotionEvent);
|
||||||
|
lJNIEnv->DeleteLocalRef(ObjectMotionEvent);
|
||||||
|
|
||||||
// Create and send our mouse wheel event
|
// Create and send our mouse wheel event
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::MouseWheelMoved;
|
event.type = Event::MouseWheelMoved;
|
||||||
@ -351,11 +354,13 @@ void WindowImplAndroid::processScrollEvent(AInputEvent* _event, ActivityStates*
|
|||||||
|
|
||||||
// Detach this thread from the JVM
|
// Detach this thread from the JVM
|
||||||
lJavaVM->DetachCurrentThread();
|
lJavaVM->DetachCurrentThread();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states)
|
int WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* states)
|
||||||
{
|
{
|
||||||
int32_t device = AInputEvent_getSource(_event);
|
int32_t device = AInputEvent_getSource(_event);
|
||||||
int32_t action = AKeyEvent_getAction(_event);
|
int32_t action = AKeyEvent_getAction(_event);
|
||||||
@ -374,7 +379,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
|||||||
case AKEY_EVENT_ACTION_DOWN:
|
case AKEY_EVENT_ACTION_DOWN:
|
||||||
event.type = Event::KeyPressed;
|
event.type = Event::KeyPressed;
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
break;
|
return 1;
|
||||||
case AKEY_EVENT_ACTION_UP:
|
case AKEY_EVENT_ACTION_UP:
|
||||||
event.type = Event::KeyReleased;
|
event.type = Event::KeyReleased;
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
@ -385,7 +390,7 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
|||||||
event.text.unicode = unicode;
|
event.text.unicode = unicode;
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
}
|
}
|
||||||
break;
|
return 1;
|
||||||
case AKEY_EVENT_ACTION_MULTIPLE:
|
case AKEY_EVENT_ACTION_MULTIPLE:
|
||||||
// Since complex inputs don't get separate key down/up events
|
// Since complex inputs don't get separate key down/up events
|
||||||
// both have to be faked at once
|
// both have to be faked at once
|
||||||
@ -400,27 +405,26 @@ void WindowImplAndroid::processKeyEvent(AInputEvent* _event, ActivityStates* sta
|
|||||||
{
|
{
|
||||||
// This is a unique sequence, which is not yet exposed in the NDK
|
// This is a unique sequence, which is not yet exposed in the NDK
|
||||||
// http://code.google.com/p/android/issues/detail?id=33998
|
// http://code.google.com/p/android/issues/detail?id=33998
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else if (int unicode = getUnicode(_event)) // This is a repeated sequence
|
||||||
{
|
{
|
||||||
// This is a repeated sequence
|
event.type = Event::TextEntered;
|
||||||
if (int unicode = getUnicode(_event))
|
event.text.unicode = unicode;
|
||||||
{
|
|
||||||
event.type = Event::TextEntered;
|
|
||||||
event.text.unicode = unicode;
|
|
||||||
|
|
||||||
int32_t repeats = AKeyEvent_getRepeatCount(_event);
|
int32_t repeats = AKeyEvent_getRepeatCount(_event);
|
||||||
for (int32_t i = 0; i < repeats; ++i)
|
for (int32_t i = 0; i < repeats; ++i)
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
}
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states)
|
int WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates* states)
|
||||||
{
|
{
|
||||||
int32_t device = AInputEvent_getSource(_event);
|
int32_t device = AInputEvent_getSource(_event);
|
||||||
int32_t action = AMotionEvent_getAction(_event);
|
int32_t action = AMotionEvent_getAction(_event);
|
||||||
@ -462,11 +466,12 @@ void WindowImplAndroid::processMotionEvent(AInputEvent* _event, ActivityStates*
|
|||||||
|
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states)
|
int WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, ActivityStates* states)
|
||||||
{
|
{
|
||||||
int32_t device = AInputEvent_getSource(_event);
|
int32_t device = AInputEvent_getSource(_event);
|
||||||
int32_t action = AMotionEvent_getAction(_event);
|
int32_t action = AMotionEvent_getAction(_event);
|
||||||
@ -525,6 +530,7 @@ void WindowImplAndroid::processPointerEvent(bool isDown, AInputEvent* _event, Ac
|
|||||||
}
|
}
|
||||||
|
|
||||||
forwardEvent(event);
|
forwardEvent(event);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -693,6 +699,9 @@ int WindowImplAndroid::getUnicode(AInputEvent* event)
|
|||||||
jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I");
|
jmethodID MethodGetUnicode = lJNIEnv->GetMethodID(ClassKeyEvent, "getUnicodeChar", "(I)I");
|
||||||
int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState);
|
int unicode = lJNIEnv->CallIntMethod(ObjectKeyEvent, MethodGetUnicode, metaState);
|
||||||
|
|
||||||
|
lJNIEnv->DeleteLocalRef(ClassKeyEvent);
|
||||||
|
lJNIEnv->DeleteLocalRef(ObjectKeyEvent);
|
||||||
|
|
||||||
// Detach this thread from the JVM
|
// Detach this thread from the JVM
|
||||||
lJavaVM->DetachCurrentThread();
|
lJavaVM->DetachCurrentThread();
|
||||||
|
|
||||||
|
@ -194,10 +194,10 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static int processEvent(int fd, int events, void* data);
|
static int processEvent(int fd, int events, void* data);
|
||||||
|
|
||||||
static void processScrollEvent(AInputEvent* _event, ActivityStates* states);
|
static int processScrollEvent(AInputEvent* _event, ActivityStates* states);
|
||||||
static void processKeyEvent(AInputEvent* _event, ActivityStates* states);
|
static int processKeyEvent(AInputEvent* _event, ActivityStates* states);
|
||||||
static void processMotionEvent(AInputEvent* _event, ActivityStates* states);
|
static int processMotionEvent(AInputEvent* _event, ActivityStates* states);
|
||||||
static void processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states);
|
static int processPointerEvent(bool isDown, AInputEvent* event, ActivityStates* states);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Convert a Android key to SFML key code
|
/// \brief Convert a Android key to SFML key code
|
||||||
|
@ -145,77 +145,6 @@ namespace
|
|||||||
|
|
||||||
return keysym;
|
return keysym;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildMap()
|
|
||||||
{
|
|
||||||
// Open a connection with the X server
|
|
||||||
xcb_connection_t* connection = sf::priv::OpenConnection();
|
|
||||||
|
|
||||||
firstKeycode = xcb_get_setup(connection)->min_keycode;
|
|
||||||
lastKeycode = xcb_get_setup(connection)->max_keycode;
|
|
||||||
|
|
||||||
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
|
||||||
|
|
||||||
sf::priv::ScopedXcbPtr<xcb_get_keyboard_mapping_reply_t> keyboardMapping(xcb_get_keyboard_mapping_reply(
|
|
||||||
connection,
|
|
||||||
xcb_get_keyboard_mapping(
|
|
||||||
connection,
|
|
||||||
firstKeycode,
|
|
||||||
lastKeycode - firstKeycode + 1
|
|
||||||
),
|
|
||||||
&error
|
|
||||||
));
|
|
||||||
|
|
||||||
sf::priv::CloseConnection(connection);
|
|
||||||
|
|
||||||
if (error || !keyboardMapping)
|
|
||||||
{
|
|
||||||
sf::err() << "Failed to get keyboard mapping" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode;
|
|
||||||
|
|
||||||
if (!keysymsPerKeycode)
|
|
||||||
{
|
|
||||||
sf::err() << "Error: No keysyms per keycode" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get());
|
|
||||||
|
|
||||||
if (!keysyms)
|
|
||||||
{
|
|
||||||
sf::err() << "Failed to get keyboard mapping keysyms" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_keycode_t range = lastKeycode - firstKeycode + 1;
|
|
||||||
|
|
||||||
std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol);
|
|
||||||
|
|
||||||
for (xcb_keycode_t i = firstKeycode; ; ++i)
|
|
||||||
{
|
|
||||||
const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode];
|
|
||||||
|
|
||||||
if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL))
|
|
||||||
{
|
|
||||||
keysymMap[i] = keysymToLower(keysym[0]);
|
|
||||||
|
|
||||||
if (i == lastKeycode)
|
|
||||||
break;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
keysymMap[i] = keysym[0];
|
|
||||||
|
|
||||||
if (i == lastKeycode)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapBuilt = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -344,11 +273,84 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists)
|
|||||||
const xcb_keysym_t* getKeysymMap()
|
const xcb_keysym_t* getKeysymMap()
|
||||||
{
|
{
|
||||||
if (!mapBuilt)
|
if (!mapBuilt)
|
||||||
buildMap();
|
buildKeysymMap();
|
||||||
|
|
||||||
return keysymMap;
|
return keysymMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void buildKeysymMap()
|
||||||
|
{
|
||||||
|
// Open a connection with the X server
|
||||||
|
xcb_connection_t* connection = sf::priv::OpenConnection();
|
||||||
|
|
||||||
|
firstKeycode = xcb_get_setup(connection)->min_keycode;
|
||||||
|
lastKeycode = xcb_get_setup(connection)->max_keycode;
|
||||||
|
|
||||||
|
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
||||||
|
|
||||||
|
sf::priv::ScopedXcbPtr<xcb_get_keyboard_mapping_reply_t> keyboardMapping(xcb_get_keyboard_mapping_reply(
|
||||||
|
connection,
|
||||||
|
xcb_get_keyboard_mapping(
|
||||||
|
connection,
|
||||||
|
firstKeycode,
|
||||||
|
lastKeycode - firstKeycode + 1
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
));
|
||||||
|
|
||||||
|
sf::priv::CloseConnection(connection);
|
||||||
|
|
||||||
|
if (error || !keyboardMapping)
|
||||||
|
{
|
||||||
|
sf::err() << "Failed to get keyboard mapping" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode;
|
||||||
|
|
||||||
|
if (!keysymsPerKeycode)
|
||||||
|
{
|
||||||
|
sf::err() << "Error: No keysyms per keycode" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get());
|
||||||
|
|
||||||
|
if (!keysyms)
|
||||||
|
{
|
||||||
|
sf::err() << "Failed to get keyboard mapping keysyms" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_keycode_t range = lastKeycode - firstKeycode + 1;
|
||||||
|
|
||||||
|
std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol);
|
||||||
|
|
||||||
|
for (xcb_keycode_t i = firstKeycode; ; ++i)
|
||||||
|
{
|
||||||
|
const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode];
|
||||||
|
|
||||||
|
if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL))
|
||||||
|
{
|
||||||
|
keysymMap[i] = keysymToLower(keysym[0]);
|
||||||
|
|
||||||
|
if (i == lastKeycode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keysymMap[i] = keysym[0];
|
||||||
|
|
||||||
|
if (i == lastKeycode)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapBuilt = true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -51,7 +51,7 @@ Display* OpenDisplay();
|
|||||||
/// \brief Get the xcb connection of the shared Display
|
/// \brief Get the xcb connection of the shared Display
|
||||||
///
|
///
|
||||||
/// This function increments the reference count of the display,
|
/// This function increments the reference count of the display,
|
||||||
/// it must be matched with a call to CloseDisplay.
|
/// it must be matched with a call to CloseConnection.
|
||||||
///
|
///
|
||||||
/// \return Pointer to the shared connection
|
/// \return Pointer to the shared connection
|
||||||
///
|
///
|
||||||
@ -127,6 +127,12 @@ xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const xcb_keysym_t* getKeysymMap();
|
const xcb_keysym_t* getKeysymMap();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Build the keysym map
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void buildKeysymMap();
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -59,113 +59,6 @@ namespace
|
|||||||
|
|
||||||
return 255;
|
return 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildMap()
|
|
||||||
{
|
|
||||||
keycodeMap[sf::Keyboard::A] = getKeycode(XK_a);
|
|
||||||
keycodeMap[sf::Keyboard::B] = getKeycode(XK_b);
|
|
||||||
keycodeMap[sf::Keyboard::C] = getKeycode(XK_c);
|
|
||||||
keycodeMap[sf::Keyboard::D] = getKeycode(XK_d);
|
|
||||||
keycodeMap[sf::Keyboard::E] = getKeycode(XK_e);
|
|
||||||
keycodeMap[sf::Keyboard::F] = getKeycode(XK_f);
|
|
||||||
keycodeMap[sf::Keyboard::G] = getKeycode(XK_g);
|
|
||||||
keycodeMap[sf::Keyboard::H] = getKeycode(XK_h);
|
|
||||||
keycodeMap[sf::Keyboard::I] = getKeycode(XK_i);
|
|
||||||
keycodeMap[sf::Keyboard::J] = getKeycode(XK_j);
|
|
||||||
keycodeMap[sf::Keyboard::K] = getKeycode(XK_k);
|
|
||||||
keycodeMap[sf::Keyboard::L] = getKeycode(XK_l);
|
|
||||||
keycodeMap[sf::Keyboard::M] = getKeycode(XK_m);
|
|
||||||
keycodeMap[sf::Keyboard::N] = getKeycode(XK_n);
|
|
||||||
keycodeMap[sf::Keyboard::O] = getKeycode(XK_o);
|
|
||||||
keycodeMap[sf::Keyboard::P] = getKeycode(XK_p);
|
|
||||||
keycodeMap[sf::Keyboard::Q] = getKeycode(XK_q);
|
|
||||||
keycodeMap[sf::Keyboard::R] = getKeycode(XK_r);
|
|
||||||
keycodeMap[sf::Keyboard::S] = getKeycode(XK_s);
|
|
||||||
keycodeMap[sf::Keyboard::T] = getKeycode(XK_t);
|
|
||||||
keycodeMap[sf::Keyboard::U] = getKeycode(XK_u);
|
|
||||||
keycodeMap[sf::Keyboard::V] = getKeycode(XK_v);
|
|
||||||
keycodeMap[sf::Keyboard::W] = getKeycode(XK_w);
|
|
||||||
keycodeMap[sf::Keyboard::X] = getKeycode(XK_x);
|
|
||||||
keycodeMap[sf::Keyboard::Y] = getKeycode(XK_y);
|
|
||||||
keycodeMap[sf::Keyboard::Z] = getKeycode(XK_z);
|
|
||||||
keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_0);
|
|
||||||
keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_1);
|
|
||||||
keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_2);
|
|
||||||
keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_3);
|
|
||||||
keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_4);
|
|
||||||
keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_5);
|
|
||||||
keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_6);
|
|
||||||
keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_7);
|
|
||||||
keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_8);
|
|
||||||
keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_9);
|
|
||||||
keycodeMap[sf::Keyboard::Escape] = getKeycode(XK_Escape);
|
|
||||||
keycodeMap[sf::Keyboard::LControl] = getKeycode(XK_Control_L);
|
|
||||||
keycodeMap[sf::Keyboard::LShift] = getKeycode(XK_Shift_L);
|
|
||||||
keycodeMap[sf::Keyboard::LAlt] = getKeycode(XK_Alt_L);
|
|
||||||
keycodeMap[sf::Keyboard::LSystem] = getKeycode(XK_Super_L);
|
|
||||||
keycodeMap[sf::Keyboard::RControl] = getKeycode(XK_Control_R);
|
|
||||||
keycodeMap[sf::Keyboard::RShift] = getKeycode(XK_Shift_R);
|
|
||||||
keycodeMap[sf::Keyboard::RAlt] = getKeycode(XK_Alt_R);
|
|
||||||
keycodeMap[sf::Keyboard::RSystem] = getKeycode(XK_Super_R);
|
|
||||||
keycodeMap[sf::Keyboard::Menu] = getKeycode(XK_Menu);
|
|
||||||
keycodeMap[sf::Keyboard::LBracket] = getKeycode(XK_bracketleft);
|
|
||||||
keycodeMap[sf::Keyboard::RBracket] = getKeycode(XK_bracketright);
|
|
||||||
keycodeMap[sf::Keyboard::SemiColon] = getKeycode(XK_semicolon);
|
|
||||||
keycodeMap[sf::Keyboard::Comma] = getKeycode(XK_comma);
|
|
||||||
keycodeMap[sf::Keyboard::Period] = getKeycode(XK_period);
|
|
||||||
keycodeMap[sf::Keyboard::Quote] = getKeycode(XK_apostrophe);
|
|
||||||
keycodeMap[sf::Keyboard::Slash] = getKeycode(XK_slash);
|
|
||||||
keycodeMap[sf::Keyboard::BackSlash] = getKeycode(XK_backslash);
|
|
||||||
keycodeMap[sf::Keyboard::Tilde] = getKeycode(XK_grave);
|
|
||||||
keycodeMap[sf::Keyboard::Equal] = getKeycode(XK_equal);
|
|
||||||
keycodeMap[sf::Keyboard::Dash] = getKeycode(XK_minus);
|
|
||||||
keycodeMap[sf::Keyboard::Space] = getKeycode(XK_space);
|
|
||||||
keycodeMap[sf::Keyboard::Return] = getKeycode(XK_Return);
|
|
||||||
keycodeMap[sf::Keyboard::BackSpace] = getKeycode(XK_BackSpace);
|
|
||||||
keycodeMap[sf::Keyboard::Tab] = getKeycode(XK_Tab);
|
|
||||||
keycodeMap[sf::Keyboard::PageUp] = getKeycode(XK_Prior);
|
|
||||||
keycodeMap[sf::Keyboard::PageDown] = getKeycode(XK_Next);
|
|
||||||
keycodeMap[sf::Keyboard::End] = getKeycode(XK_End);
|
|
||||||
keycodeMap[sf::Keyboard::Home] = getKeycode(XK_Home);
|
|
||||||
keycodeMap[sf::Keyboard::Insert] = getKeycode(XK_Insert);
|
|
||||||
keycodeMap[sf::Keyboard::Delete] = getKeycode(XK_Delete);
|
|
||||||
keycodeMap[sf::Keyboard::Add] = getKeycode(XK_KP_Add);
|
|
||||||
keycodeMap[sf::Keyboard::Subtract] = getKeycode(XK_KP_Subtract);
|
|
||||||
keycodeMap[sf::Keyboard::Multiply] = getKeycode(XK_KP_Multiply);
|
|
||||||
keycodeMap[sf::Keyboard::Divide] = getKeycode(XK_KP_Divide);
|
|
||||||
keycodeMap[sf::Keyboard::Left] = getKeycode(XK_Left);
|
|
||||||
keycodeMap[sf::Keyboard::Right] = getKeycode(XK_Right);
|
|
||||||
keycodeMap[sf::Keyboard::Up] = getKeycode(XK_Up);
|
|
||||||
keycodeMap[sf::Keyboard::Down] = getKeycode(XK_Down);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad0] = getKeycode(XK_KP_0);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad1] = getKeycode(XK_KP_1);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad2] = getKeycode(XK_KP_2);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad3] = getKeycode(XK_KP_3);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad4] = getKeycode(XK_KP_4);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad5] = getKeycode(XK_KP_5);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad6] = getKeycode(XK_KP_6);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad7] = getKeycode(XK_KP_7);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad8] = getKeycode(XK_KP_8);
|
|
||||||
keycodeMap[sf::Keyboard::Numpad9] = getKeycode(XK_KP_9);
|
|
||||||
keycodeMap[sf::Keyboard::F1] = getKeycode(XK_F1);
|
|
||||||
keycodeMap[sf::Keyboard::F2] = getKeycode(XK_F2);
|
|
||||||
keycodeMap[sf::Keyboard::F3] = getKeycode(XK_F3);
|
|
||||||
keycodeMap[sf::Keyboard::F4] = getKeycode(XK_F4);
|
|
||||||
keycodeMap[sf::Keyboard::F5] = getKeycode(XK_F5);
|
|
||||||
keycodeMap[sf::Keyboard::F6] = getKeycode(XK_F6);
|
|
||||||
keycodeMap[sf::Keyboard::F7] = getKeycode(XK_F7);
|
|
||||||
keycodeMap[sf::Keyboard::F8] = getKeycode(XK_F8);
|
|
||||||
keycodeMap[sf::Keyboard::F9] = getKeycode(XK_F9);
|
|
||||||
keycodeMap[sf::Keyboard::F10] = getKeycode(XK_F10);
|
|
||||||
keycodeMap[sf::Keyboard::F11] = getKeycode(XK_F11);
|
|
||||||
keycodeMap[sf::Keyboard::F12] = getKeycode(XK_F12);
|
|
||||||
keycodeMap[sf::Keyboard::F13] = getKeycode(XK_F13);
|
|
||||||
keycodeMap[sf::Keyboard::F14] = getKeycode(XK_F14);
|
|
||||||
keycodeMap[sf::Keyboard::F15] = getKeycode(XK_F15);
|
|
||||||
keycodeMap[sf::Keyboard::Pause] = getKeycode(XK_Pause);
|
|
||||||
|
|
||||||
mapBuilt = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -423,6 +316,115 @@ Vector2i InputImpl::getTouchPosition(unsigned int /*finger*/, const Window& /*re
|
|||||||
return Vector2i();
|
return Vector2i();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void InputImpl::buildMap()
|
||||||
|
{
|
||||||
|
keycodeMap[sf::Keyboard::A] = getKeycode(XK_a);
|
||||||
|
keycodeMap[sf::Keyboard::B] = getKeycode(XK_b);
|
||||||
|
keycodeMap[sf::Keyboard::C] = getKeycode(XK_c);
|
||||||
|
keycodeMap[sf::Keyboard::D] = getKeycode(XK_d);
|
||||||
|
keycodeMap[sf::Keyboard::E] = getKeycode(XK_e);
|
||||||
|
keycodeMap[sf::Keyboard::F] = getKeycode(XK_f);
|
||||||
|
keycodeMap[sf::Keyboard::G] = getKeycode(XK_g);
|
||||||
|
keycodeMap[sf::Keyboard::H] = getKeycode(XK_h);
|
||||||
|
keycodeMap[sf::Keyboard::I] = getKeycode(XK_i);
|
||||||
|
keycodeMap[sf::Keyboard::J] = getKeycode(XK_j);
|
||||||
|
keycodeMap[sf::Keyboard::K] = getKeycode(XK_k);
|
||||||
|
keycodeMap[sf::Keyboard::L] = getKeycode(XK_l);
|
||||||
|
keycodeMap[sf::Keyboard::M] = getKeycode(XK_m);
|
||||||
|
keycodeMap[sf::Keyboard::N] = getKeycode(XK_n);
|
||||||
|
keycodeMap[sf::Keyboard::O] = getKeycode(XK_o);
|
||||||
|
keycodeMap[sf::Keyboard::P] = getKeycode(XK_p);
|
||||||
|
keycodeMap[sf::Keyboard::Q] = getKeycode(XK_q);
|
||||||
|
keycodeMap[sf::Keyboard::R] = getKeycode(XK_r);
|
||||||
|
keycodeMap[sf::Keyboard::S] = getKeycode(XK_s);
|
||||||
|
keycodeMap[sf::Keyboard::T] = getKeycode(XK_t);
|
||||||
|
keycodeMap[sf::Keyboard::U] = getKeycode(XK_u);
|
||||||
|
keycodeMap[sf::Keyboard::V] = getKeycode(XK_v);
|
||||||
|
keycodeMap[sf::Keyboard::W] = getKeycode(XK_w);
|
||||||
|
keycodeMap[sf::Keyboard::X] = getKeycode(XK_x);
|
||||||
|
keycodeMap[sf::Keyboard::Y] = getKeycode(XK_y);
|
||||||
|
keycodeMap[sf::Keyboard::Z] = getKeycode(XK_z);
|
||||||
|
keycodeMap[sf::Keyboard::Num0] = getKeycode(XK_0);
|
||||||
|
keycodeMap[sf::Keyboard::Num1] = getKeycode(XK_1);
|
||||||
|
keycodeMap[sf::Keyboard::Num2] = getKeycode(XK_2);
|
||||||
|
keycodeMap[sf::Keyboard::Num3] = getKeycode(XK_3);
|
||||||
|
keycodeMap[sf::Keyboard::Num4] = getKeycode(XK_4);
|
||||||
|
keycodeMap[sf::Keyboard::Num5] = getKeycode(XK_5);
|
||||||
|
keycodeMap[sf::Keyboard::Num6] = getKeycode(XK_6);
|
||||||
|
keycodeMap[sf::Keyboard::Num7] = getKeycode(XK_7);
|
||||||
|
keycodeMap[sf::Keyboard::Num8] = getKeycode(XK_8);
|
||||||
|
keycodeMap[sf::Keyboard::Num9] = getKeycode(XK_9);
|
||||||
|
keycodeMap[sf::Keyboard::Escape] = getKeycode(XK_Escape);
|
||||||
|
keycodeMap[sf::Keyboard::LControl] = getKeycode(XK_Control_L);
|
||||||
|
keycodeMap[sf::Keyboard::LShift] = getKeycode(XK_Shift_L);
|
||||||
|
keycodeMap[sf::Keyboard::LAlt] = getKeycode(XK_Alt_L);
|
||||||
|
keycodeMap[sf::Keyboard::LSystem] = getKeycode(XK_Super_L);
|
||||||
|
keycodeMap[sf::Keyboard::RControl] = getKeycode(XK_Control_R);
|
||||||
|
keycodeMap[sf::Keyboard::RShift] = getKeycode(XK_Shift_R);
|
||||||
|
keycodeMap[sf::Keyboard::RAlt] = getKeycode(XK_Alt_R);
|
||||||
|
keycodeMap[sf::Keyboard::RSystem] = getKeycode(XK_Super_R);
|
||||||
|
keycodeMap[sf::Keyboard::Menu] = getKeycode(XK_Menu);
|
||||||
|
keycodeMap[sf::Keyboard::LBracket] = getKeycode(XK_bracketleft);
|
||||||
|
keycodeMap[sf::Keyboard::RBracket] = getKeycode(XK_bracketright);
|
||||||
|
keycodeMap[sf::Keyboard::SemiColon] = getKeycode(XK_semicolon);
|
||||||
|
keycodeMap[sf::Keyboard::Comma] = getKeycode(XK_comma);
|
||||||
|
keycodeMap[sf::Keyboard::Period] = getKeycode(XK_period);
|
||||||
|
keycodeMap[sf::Keyboard::Quote] = getKeycode(XK_apostrophe);
|
||||||
|
keycodeMap[sf::Keyboard::Slash] = getKeycode(XK_slash);
|
||||||
|
keycodeMap[sf::Keyboard::BackSlash] = getKeycode(XK_backslash);
|
||||||
|
keycodeMap[sf::Keyboard::Tilde] = getKeycode(XK_grave);
|
||||||
|
keycodeMap[sf::Keyboard::Equal] = getKeycode(XK_equal);
|
||||||
|
keycodeMap[sf::Keyboard::Dash] = getKeycode(XK_minus);
|
||||||
|
keycodeMap[sf::Keyboard::Space] = getKeycode(XK_space);
|
||||||
|
keycodeMap[sf::Keyboard::Return] = getKeycode(XK_Return);
|
||||||
|
keycodeMap[sf::Keyboard::BackSpace] = getKeycode(XK_BackSpace);
|
||||||
|
keycodeMap[sf::Keyboard::Tab] = getKeycode(XK_Tab);
|
||||||
|
keycodeMap[sf::Keyboard::PageUp] = getKeycode(XK_Prior);
|
||||||
|
keycodeMap[sf::Keyboard::PageDown] = getKeycode(XK_Next);
|
||||||
|
keycodeMap[sf::Keyboard::End] = getKeycode(XK_End);
|
||||||
|
keycodeMap[sf::Keyboard::Home] = getKeycode(XK_Home);
|
||||||
|
keycodeMap[sf::Keyboard::Insert] = getKeycode(XK_Insert);
|
||||||
|
keycodeMap[sf::Keyboard::Delete] = getKeycode(XK_Delete);
|
||||||
|
keycodeMap[sf::Keyboard::Add] = getKeycode(XK_KP_Add);
|
||||||
|
keycodeMap[sf::Keyboard::Subtract] = getKeycode(XK_KP_Subtract);
|
||||||
|
keycodeMap[sf::Keyboard::Multiply] = getKeycode(XK_KP_Multiply);
|
||||||
|
keycodeMap[sf::Keyboard::Divide] = getKeycode(XK_KP_Divide);
|
||||||
|
keycodeMap[sf::Keyboard::Left] = getKeycode(XK_Left);
|
||||||
|
keycodeMap[sf::Keyboard::Right] = getKeycode(XK_Right);
|
||||||
|
keycodeMap[sf::Keyboard::Up] = getKeycode(XK_Up);
|
||||||
|
keycodeMap[sf::Keyboard::Down] = getKeycode(XK_Down);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad0] = getKeycode(XK_KP_0);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad1] = getKeycode(XK_KP_1);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad2] = getKeycode(XK_KP_2);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad3] = getKeycode(XK_KP_3);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad4] = getKeycode(XK_KP_4);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad5] = getKeycode(XK_KP_5);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad6] = getKeycode(XK_KP_6);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad7] = getKeycode(XK_KP_7);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad8] = getKeycode(XK_KP_8);
|
||||||
|
keycodeMap[sf::Keyboard::Numpad9] = getKeycode(XK_KP_9);
|
||||||
|
keycodeMap[sf::Keyboard::F1] = getKeycode(XK_F1);
|
||||||
|
keycodeMap[sf::Keyboard::F2] = getKeycode(XK_F2);
|
||||||
|
keycodeMap[sf::Keyboard::F3] = getKeycode(XK_F3);
|
||||||
|
keycodeMap[sf::Keyboard::F4] = getKeycode(XK_F4);
|
||||||
|
keycodeMap[sf::Keyboard::F5] = getKeycode(XK_F5);
|
||||||
|
keycodeMap[sf::Keyboard::F6] = getKeycode(XK_F6);
|
||||||
|
keycodeMap[sf::Keyboard::F7] = getKeycode(XK_F7);
|
||||||
|
keycodeMap[sf::Keyboard::F8] = getKeycode(XK_F8);
|
||||||
|
keycodeMap[sf::Keyboard::F9] = getKeycode(XK_F9);
|
||||||
|
keycodeMap[sf::Keyboard::F10] = getKeycode(XK_F10);
|
||||||
|
keycodeMap[sf::Keyboard::F11] = getKeycode(XK_F11);
|
||||||
|
keycodeMap[sf::Keyboard::F12] = getKeycode(XK_F12);
|
||||||
|
keycodeMap[sf::Keyboard::F13] = getKeycode(XK_F13);
|
||||||
|
keycodeMap[sf::Keyboard::F14] = getKeycode(XK_F14);
|
||||||
|
keycodeMap[sf::Keyboard::F15] = getKeycode(XK_F15);
|
||||||
|
keycodeMap[sf::Keyboard::Pause] = getKeycode(XK_Pause);
|
||||||
|
|
||||||
|
mapBuilt = true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -158,6 +158,12 @@ public:
|
|||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static Vector2i getTouchPosition(unsigned int finger, const Window& relativeTo);
|
static Vector2i getTouchPosition(unsigned int finger, const Window& relativeTo);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Build the SFML to X11 keymap
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void buildMap();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
|
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
|
||||||
#include <SFML/Window/Unix/WindowImplX11.hpp>
|
#include <SFML/Window/Unix/WindowImplX11.hpp>
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
|
#include <SFML/Window/Unix/InputImpl.hpp>
|
||||||
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
|
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
@ -50,6 +51,10 @@
|
|||||||
#define XCB_DRI2_BUFFER_SWAP_COMPLETE 0
|
#define XCB_DRI2_BUFFER_SWAP_COMPLETE 0
|
||||||
#define XCB_DRI2_INVALIDATE_BUFFERS 1
|
#define XCB_DRI2_INVALIDATE_BUFFERS 1
|
||||||
|
|
||||||
|
// So we don't have to require xcb xkb to be present
|
||||||
|
#define XCB_XKB_NEW_KEYBOARD_NOTIFY 0
|
||||||
|
#define XCB_XKB_MAP_NOTIFY 1
|
||||||
|
|
||||||
#ifdef SFML_OPENGL_ES
|
#ifdef SFML_OPENGL_ES
|
||||||
#include <SFML/Window/EglContext.hpp>
|
#include <SFML/Window/EglContext.hpp>
|
||||||
typedef sf::priv::EglContext ContextType;
|
typedef sf::priv::EglContext ContextType;
|
||||||
@ -230,28 +235,27 @@ namespace
|
|||||||
|
|
||||||
sf::priv::CloseConnection(connection);
|
sf::priv::CloseConnection(connection);
|
||||||
|
|
||||||
const char* name = reinterpret_cast<const char*>(xcb_get_property_value(wmName.get()));
|
// It seems the wm name string reply is not necessarily
|
||||||
|
// null-terminated. The work around is to get its actual
|
||||||
windowManagerName = name;
|
// length to build a proper string
|
||||||
|
const char* begin = reinterpret_cast<const char*>(xcb_get_property_value(wmName.get()));
|
||||||
|
const char* end = begin + xcb_get_property_value_length(wmName.get());
|
||||||
|
windowManagerName = sf::String::fromUtf8(begin, end);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_query_extension_reply_t getDriExtension()
|
xcb_query_extension_reply_t getXExtension(const std::string& name)
|
||||||
{
|
{
|
||||||
xcb_connection_t* connection = sf::priv::OpenConnection();
|
xcb_connection_t* connection = sf::priv::OpenConnection();
|
||||||
|
|
||||||
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);
|
||||||
|
sf::priv::ScopedXcbPtr<xcb_query_extension_reply_t> extension(xcb_query_extension_reply(
|
||||||
// Check if the DRI2 extension is present
|
|
||||||
// We don't use xcb_get_extension_data here to avoid having to link to xcb_dri2
|
|
||||||
static const std::string DRI2 = "DRI2";
|
|
||||||
sf::priv::ScopedXcbPtr<xcb_query_extension_reply_t> driExt(xcb_query_extension_reply(
|
|
||||||
connection,
|
connection,
|
||||||
xcb_query_extension(
|
xcb_query_extension(
|
||||||
connection,
|
connection,
|
||||||
DRI2.size(),
|
name.size(),
|
||||||
DRI2.c_str()
|
name.c_str()
|
||||||
),
|
),
|
||||||
&error
|
&error
|
||||||
));
|
));
|
||||||
@ -259,14 +263,14 @@ namespace
|
|||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
sf::priv::CloseConnection(connection);
|
sf::priv::CloseConnection(connection);
|
||||||
|
|
||||||
if (error || !driExt || !driExt->present)
|
if (error || !extension || !extension->present)
|
||||||
{
|
{
|
||||||
xcb_query_extension_reply_t reply;
|
xcb_query_extension_reply_t reply;
|
||||||
std::memset(&reply, 0, sizeof(reply));
|
std::memset(&reply, 0, sizeof(reply));
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *driExt.get();
|
return *extension.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpXcbExtensions()
|
void dumpXcbExtensions()
|
||||||
@ -1926,12 +1930,21 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
if (passEvent(windowEvent, reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent)->window))
|
if (passEvent(windowEvent, reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent)->window))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// X notifies about "window configuration events", which also includes moving a window only. Check
|
||||||
|
// for a different size and only spawn a Resized event when it differs.
|
||||||
xcb_configure_notify_event_t* e = reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent);
|
xcb_configure_notify_event_t* e = reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent);
|
||||||
Event event;
|
|
||||||
event.type = Event::Resized;
|
if (e->width != m_previousSize.x || e->height != m_previousSize.y)
|
||||||
event.size.width = e->width;
|
{
|
||||||
event.size.height = e->height;
|
m_previousSize.x = e->width;
|
||||||
pushEvent(event);
|
m_previousSize.y = e->height;
|
||||||
|
|
||||||
|
Event event;
|
||||||
|
event.type = Event::Resized;
|
||||||
|
event.size.width = e->width;
|
||||||
|
event.size.height = e->height;
|
||||||
|
pushEvent(event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2251,8 +2264,18 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
|
|
||||||
// Handle any extension events first
|
// Handle any extension events first
|
||||||
|
|
||||||
|
// SHAPE
|
||||||
|
// Ubuntu's Unity desktop environment makes use of the
|
||||||
|
// Compiz compositing window manager
|
||||||
|
// Compiz seems to send SHAPE events to windows even if they
|
||||||
|
// did not specifically select those events
|
||||||
|
// We ignore those events here in order to not generate warnings
|
||||||
|
static xcb_query_extension_reply_t shapeExtension = getXExtension("SHAPE");
|
||||||
|
if (shapeExtension.present && (responseType == shapeExtension.first_event))
|
||||||
|
break;
|
||||||
|
|
||||||
// DRI2
|
// DRI2
|
||||||
static xcb_query_extension_reply_t driExtension = getDriExtension();
|
static xcb_query_extension_reply_t driExtension = getXExtension("DRI2");
|
||||||
if (driExtension.present)
|
if (driExtension.present)
|
||||||
{
|
{
|
||||||
// Because we are using the XCB event queue instead of the Xlib event
|
// Because we are using the XCB event queue instead of the Xlib event
|
||||||
@ -2302,6 +2325,57 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XKEYBOARD
|
||||||
|
// When the X server sends us XKEYBOARD events, it means that
|
||||||
|
// the user probably changed the layout of their keyboard
|
||||||
|
// We update our keymaps in that case
|
||||||
|
static xcb_query_extension_reply_t xkeyboardExtension = getXExtension("XKEYBOARD");
|
||||||
|
if (xkeyboardExtension.present && (responseType == xkeyboardExtension.first_event))
|
||||||
|
{
|
||||||
|
// We do this so we don't have to include the xkb header for the struct declaration
|
||||||
|
uint8_t xkbType = reinterpret_cast<const uint8_t*>(windowEvent)[1];
|
||||||
|
|
||||||
|
// We only bother rebuilding our maps if the xkb mapping actually changes
|
||||||
|
if ((xkbType == XCB_XKB_NEW_KEYBOARD_NOTIFY) || (xkbType == XCB_XKB_MAP_NOTIFY))
|
||||||
|
{
|
||||||
|
// keysym map
|
||||||
|
buildKeysymMap();
|
||||||
|
|
||||||
|
// keycode to SFML
|
||||||
|
buildMap();
|
||||||
|
|
||||||
|
// SFML to keycode
|
||||||
|
InputImpl::buildMap();
|
||||||
|
|
||||||
|
// XInputMethod expects keyboard mapping changes to be propagated to it
|
||||||
|
// Same idea here as with the DRI2 events above
|
||||||
|
|
||||||
|
// We lock/unlock the display to protect against concurrent access
|
||||||
|
XLockDisplay(m_display);
|
||||||
|
|
||||||
|
typedef Bool (*wireEventHandler)(Display*, XEvent*, xEvent*);
|
||||||
|
|
||||||
|
// Probe for any handlers that are registered for this event type
|
||||||
|
wireEventHandler handler = XESetWireToEvent(m_display, responseType, 0);
|
||||||
|
|
||||||
|
if (handler)
|
||||||
|
{
|
||||||
|
// Restore the previous handler if one was registered
|
||||||
|
XESetWireToEvent(m_display, responseType, handler);
|
||||||
|
|
||||||
|
XEvent event;
|
||||||
|
windowEvent->sequence = LastKnownRequestProcessed(m_display);
|
||||||
|
|
||||||
|
// Pretend to be the Xlib event queue
|
||||||
|
handler(m_display, &event, reinterpret_cast<xEvent*>(windowEvent));
|
||||||
|
}
|
||||||
|
|
||||||
|
XUnlockDisplay(m_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Print any surprises to stderr (would be nice if people report when this happens)
|
// Print any surprises to stderr (would be nice if people report when this happens)
|
||||||
dumpUnhandledEvent(responseType);
|
dumpUnhandledEvent(responseType);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user