commit
6bd362ea7e
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -18,8 +18,8 @@ jobs:
|
|||||||
- { name: Windows VS2022 Clang, os: windows-2022, flags: -T ClangCL }
|
- { name: Windows VS2022 Clang, os: windows-2022, flags: -T ClangCL }
|
||||||
- { name: Linux GCC, os: ubuntu-latest }
|
- { name: Linux GCC, os: ubuntu-latest }
|
||||||
- { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++, gcovr_options: '--gcov-executable="llvm-cov-$CLANG_VERSION gcov"' }
|
- { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++, gcovr_options: '--gcov-executable="llvm-cov-$CLANG_VERSION gcov"' }
|
||||||
- { name: MacOS, os: macos-latest }
|
- { name: MacOS, os: macos-11 }
|
||||||
- { name: MacOS Xcode, os: macos-latest, flags: -GXcode }
|
- { name: MacOS Xcode, os: macos-11, flags: -GXcode }
|
||||||
config:
|
config:
|
||||||
- { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE }
|
- { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE }
|
||||||
- { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE }
|
- { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE }
|
||||||
@ -34,9 +34,9 @@ jobs:
|
|||||||
- platform: { name: Windows VS2022, os: windows-2022 }
|
- platform: { name: Windows VS2022, os: windows-2022 }
|
||||||
config: { name: Unity, flags: -DBUILD_SHARED_LIBS=TRUE -DCMAKE_UNITY_BUILD=ON }
|
config: { name: Unity, flags: -DBUILD_SHARED_LIBS=TRUE -DCMAKE_UNITY_BUILD=ON }
|
||||||
type: { name: Debug, flags: -DCMAKE_BUILD_TYPE=Debug -DSFML_ENABLE_COVERAGE=TRUE }
|
type: { name: Debug, flags: -DCMAKE_BUILD_TYPE=Debug -DSFML_ENABLE_COVERAGE=TRUE }
|
||||||
- platform: { name: MacOS, os: macos-latest }
|
- platform: { name: MacOS, os: macos-11 }
|
||||||
config: { name: Frameworks, flags: -DSFML_BUILD_FRAMEWORKS=TRUE }
|
config: { name: Frameworks, flags: -DSFML_BUILD_FRAMEWORKS=TRUE }
|
||||||
- platform: { name: MacOS, os: macos-latest }
|
- platform: { name: MacOS, os: macos-11 }
|
||||||
config: { name: iOS, flags: -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchains/iOS.toolchain.cmake -DIOS_PLATFORM=SIMULATOR }
|
config: { name: iOS, flags: -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchains/iOS.toolchain.cmake -DIOS_PLATFORM=SIMULATOR }
|
||||||
- platform: { name: Android, os: ubuntu-latest }
|
- platform: { name: Android, os: ubuntu-latest }
|
||||||
config: { name: x86, flags: -DCMAKE_ANDROID_ARCH_ABI=x86 -DCMAKE_SYSTEM_NAME=Android -DSFML_BUILD_TEST_SUITE=FALSE -DCMAKE_ANDROID_NDK=$GITHUB_WORKSPACE/android-ndk-r23b -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang -DCMAKE_ANDROID_STL_TYPE=c++_shared -DCMAKE_ANDROID_API=26 }
|
config: { name: x86, flags: -DCMAKE_ANDROID_ARCH_ABI=x86 -DCMAKE_SYSTEM_NAME=Android -DSFML_BUILD_TEST_SUITE=FALSE -DCMAKE_ANDROID_NDK=$GITHUB_WORKSPACE/android-ndk-r23b -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang -DCMAKE_ANDROID_STL_TYPE=c++_shared -DCMAKE_ANDROID_API=26 }
|
||||||
|
66
extlibs/headers/drm/drm-common.c
vendored
66
extlibs/headers/drm/drm-common.c
vendored
@ -170,6 +170,26 @@ static int get_resources(int fd, drmModeRes **resources)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int has_monitor_connected(int fd, drmModeRes* resources)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
drmModeConnector *connector;
|
||||||
|
for (i = 0; i < resources->count_connectors; i++)
|
||||||
|
{
|
||||||
|
connector = drmModeGetConnector(fd, resources->connectors[i]);
|
||||||
|
if (connector->connection == DRM_MODE_CONNECTED)
|
||||||
|
{
|
||||||
|
/* There is a monitor connected */
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_DRM_DEVICES 64
|
#define MAX_DRM_DEVICES 64
|
||||||
|
|
||||||
static int find_drm_device(drmModeRes **resources)
|
static int find_drm_device(drmModeRes **resources)
|
||||||
@ -199,7 +219,11 @@ static int find_drm_device(drmModeRes **resources)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
continue;
|
continue;
|
||||||
ret = get_resources(fd, resources);
|
ret = get_resources(fd, resources);
|
||||||
if (!ret)
|
if(getenv("SFML_DRM_DEBUG"))
|
||||||
|
{
|
||||||
|
printf("DRM device used: %d\n", i);
|
||||||
|
}
|
||||||
|
if(!ret && has_monitor_connected(fd, *resources) != 0)
|
||||||
break;
|
break;
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
@ -285,34 +309,6 @@ int init_drm(struct drm *drm, const char *device, const char *mode_str,
|
|||||||
printf("requested mode not found, using default mode!\n");
|
printf("requested mode not found, using default mode!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find preferred mode or the highest resolution mode: */
|
|
||||||
if (!drm->mode)
|
|
||||||
{
|
|
||||||
for (i = 0, area = 0; i < connector->count_modes; i++)
|
|
||||||
{
|
|
||||||
drmModeModeInfo *current_mode = &connector->modes[i];
|
|
||||||
|
|
||||||
if (current_mode->type & DRM_MODE_TYPE_PREFERRED)
|
|
||||||
{
|
|
||||||
drm->mode = current_mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int current_area = current_mode->hdisplay * current_mode->vdisplay;
|
|
||||||
if (current_area > area)
|
|
||||||
{
|
|
||||||
drm->mode = current_mode;
|
|
||||||
area = current_area;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!drm->mode)
|
|
||||||
{
|
|
||||||
printf("could not find mode!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find encoder: */
|
/* find encoder: */
|
||||||
for (i = 0; i < resources->count_encoders; i++)
|
for (i = 0; i < resources->count_encoders; i++)
|
||||||
{
|
{
|
||||||
@ -349,7 +345,17 @@ int init_drm(struct drm *drm, const char *device, const char *mode_str,
|
|||||||
// get original display mode so we can restore display mode after program exits
|
// get original display mode so we can restore display mode after program exits
|
||||||
drm->original_crtc = drmModeGetCrtc(drm->fd, drm->crtc_id);
|
drm->original_crtc = drmModeGetCrtc(drm->fd, drm->crtc_id);
|
||||||
|
|
||||||
if(getenv("SFML_DRM_DEBUG"))
|
/* Let's use the current mode rather than the preferred one if the user didn't
|
||||||
|
* specify a mode with env vars
|
||||||
|
*/
|
||||||
|
if (!drm->mode)
|
||||||
|
{
|
||||||
|
if(getenv("SFML_DRM_DEBUG"))
|
||||||
|
printf("DRM using the current mode\n");
|
||||||
|
drm->mode = &(drm->original_crtc->mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv("SFML_DRM_DEBUG"))
|
||||||
{
|
{
|
||||||
printf("DRM Mode used: %s@%d\n", drm->mode->name, drm->mode->vrefresh);
|
printf("DRM Mode used: %s@%d\n", drm->mode->name, drm->mode->vrefresh);
|
||||||
}
|
}
|
||||||
|
@ -91,14 +91,18 @@ void cleanup()
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
drmModeSetCrtc(drmNode.fd,
|
/* Avoid a modeswitch if possible */
|
||||||
drmNode.original_crtc->crtc_id,
|
if (drmNode.mode != &drmNode.original_crtc->mode)
|
||||||
drmNode.original_crtc->buffer_id,
|
drmModeSetCrtc(drmNode.fd,
|
||||||
drmNode.original_crtc->x,
|
drmNode.original_crtc->crtc_id,
|
||||||
drmNode.original_crtc->y,
|
drmNode.original_crtc->buffer_id,
|
||||||
&drmNode.connector_id,
|
drmNode.original_crtc->x,
|
||||||
1,
|
drmNode.original_crtc->y,
|
||||||
&drmNode.original_crtc->mode);
|
&drmNode.connector_id,
|
||||||
|
1,
|
||||||
|
&drmNode.original_crtc->mode);
|
||||||
|
else if (getenv("SFML_DRM_DEBUG"))
|
||||||
|
printf("DRM keeping the same mode since using the original one\n");
|
||||||
|
|
||||||
drmModeFreeConnector(drmNode.saved_connector);
|
drmModeFreeConnector(drmNode.saved_connector);
|
||||||
drmModeFreeEncoder(drmNode.saved_encoder);
|
drmModeFreeEncoder(drmNode.saved_encoder);
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <bitset>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -77,6 +78,7 @@ namespace WindowsImplX11Impl
|
|||||||
{
|
{
|
||||||
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
|
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
|
||||||
std::vector<sf::priv::WindowImplX11*> allWindows;
|
std::vector<sf::priv::WindowImplX11*> allWindows;
|
||||||
|
std::bitset<256> isKeyFiltered;
|
||||||
std::recursive_mutex allWindowsMutex;
|
std::recursive_mutex allWindowsMutex;
|
||||||
sf::String windowManagerName;
|
sf::String windowManagerName;
|
||||||
|
|
||||||
@ -88,23 +90,6 @@ constexpr unsigned long eventMask = FocusChangeMask | ButtonPressMask | ButtonRe
|
|||||||
|
|
||||||
constexpr unsigned int maxTrialsCount = 5;
|
constexpr unsigned int maxTrialsCount = 5;
|
||||||
|
|
||||||
// Predicate we use to find key repeat events in processEvent
|
|
||||||
struct KeyRepeatFinder
|
|
||||||
{
|
|
||||||
KeyRepeatFinder(unsigned int initalKeycode, Time initialTime) : keycode(initalKeycode), time(initialTime)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Predicate operator that checks event type, keycode and timestamp
|
|
||||||
bool operator()(const XEvent& event)
|
|
||||||
{
|
|
||||||
return ((event.type == KeyPress) && (event.xkey.keycode == keycode) && (event.xkey.time - time < 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int keycode;
|
|
||||||
Time time;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Filter the events received by windows (only allow those matching a specific window)
|
// Filter the events received by windows (only allow those matching a specific window)
|
||||||
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
||||||
{
|
{
|
||||||
@ -831,14 +816,61 @@ void WindowImplX11::processEvents()
|
|||||||
|
|
||||||
// Pick out the events that are interesting for this window
|
// Pick out the events that are interesting for this window
|
||||||
while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
|
while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
|
||||||
m_events.push_back(event);
|
|
||||||
|
|
||||||
// Handle the events for this window that we just picked out
|
|
||||||
while (!m_events.empty())
|
|
||||||
{
|
{
|
||||||
event = m_events.front();
|
// This function implements a workaround to properly discard
|
||||||
m_events.pop_front();
|
// repeated key events when necessary. The problem is that the
|
||||||
processEvent(event);
|
// system's key events policy doesn't match SFML's one: X server will generate
|
||||||
|
// both repeated KeyPress and KeyRelease events when maintaining a key down, while
|
||||||
|
// SFML only wants repeated KeyPress events. Thus, we have to:
|
||||||
|
// - Discard duplicated KeyRelease events when m_keyRepeat is true
|
||||||
|
// - Discard both duplicated KeyPress and KeyRelease events when m_keyRepeat is false
|
||||||
|
|
||||||
|
bool processThisEvent = true;
|
||||||
|
|
||||||
|
// Detect repeated key events
|
||||||
|
while (event.type == KeyRelease)
|
||||||
|
{
|
||||||
|
XEvent nextEvent;
|
||||||
|
if (XCheckIfEvent(m_display, &nextEvent, checkEvent, reinterpret_cast<XPointer>(m_window)))
|
||||||
|
{
|
||||||
|
if ((nextEvent.type == KeyPress) && (nextEvent.xkey.keycode == event.xkey.keycode) &&
|
||||||
|
(event.xkey.time <= nextEvent.xkey.time) && (nextEvent.xkey.time <= event.xkey.time + 1))
|
||||||
|
{
|
||||||
|
// This sequence of events comes from maintaining a key down
|
||||||
|
if (m_keyRepeat)
|
||||||
|
{
|
||||||
|
// Ignore the KeyRelease event and process the KeyPress event
|
||||||
|
event = nextEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Ignore both events
|
||||||
|
processThisEvent = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This sequence of events does not come from maintaining a key down,
|
||||||
|
// so process the KeyRelease event normally,
|
||||||
|
processEvent(event);
|
||||||
|
// but loop because the next event can be the first half
|
||||||
|
// of a sequence coming from maintaining a key down.
|
||||||
|
event = nextEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No event after this KeyRelease event so assume it can be processed.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processThisEvent)
|
||||||
|
{
|
||||||
|
processEvent(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process clipboard window events
|
// Process clipboard window events
|
||||||
@ -1731,33 +1763,6 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
|||||||
{
|
{
|
||||||
using namespace WindowsImplX11Impl;
|
using namespace WindowsImplX11Impl;
|
||||||
|
|
||||||
// This function implements a workaround to properly discard
|
|
||||||
// repeated key events when necessary. The problem is that the
|
|
||||||
// system's key events policy doesn't match SFML's one: X server will generate
|
|
||||||
// both repeated KeyPress and KeyRelease events when maintaining a key down, while
|
|
||||||
// SFML only wants repeated KeyPress events. Thus, we have to:
|
|
||||||
// - Discard duplicated KeyRelease events when KeyRepeatEnabled is true
|
|
||||||
// - Discard both duplicated KeyPress and KeyRelease events when KeyRepeatEnabled is false
|
|
||||||
|
|
||||||
// Detect repeated key events
|
|
||||||
if (windowEvent.type == KeyRelease)
|
|
||||||
{
|
|
||||||
// Find the next KeyPress event with matching keycode and time
|
|
||||||
auto it = std::find_if(m_events.begin(),
|
|
||||||
m_events.end(),
|
|
||||||
KeyRepeatFinder(windowEvent.xkey.keycode, windowEvent.xkey.time));
|
|
||||||
|
|
||||||
if (it != m_events.end())
|
|
||||||
{
|
|
||||||
// If we don't want repeated events, remove the next KeyPress from the queue
|
|
||||||
if (!m_keyRepeat)
|
|
||||||
m_events.erase(it);
|
|
||||||
|
|
||||||
// This KeyRelease is a repeated event and we don't want it
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the X11 event to a sf::Event
|
// Convert the X11 event to a sf::Event
|
||||||
switch (windowEvent.type)
|
switch (windowEvent.type)
|
||||||
{
|
{
|
||||||
@ -1913,10 +1918,30 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
|||||||
event.key.control = windowEvent.xkey.state & ControlMask;
|
event.key.control = windowEvent.xkey.state & ControlMask;
|
||||||
event.key.shift = windowEvent.xkey.state & ShiftMask;
|
event.key.shift = windowEvent.xkey.state & ShiftMask;
|
||||||
event.key.system = windowEvent.xkey.state & Mod4Mask;
|
event.key.system = windowEvent.xkey.state & Mod4Mask;
|
||||||
pushEvent(event);
|
|
||||||
|
|
||||||
// Generate a TextEntered event
|
const bool filtered = XFilterEvent(&windowEvent, None);
|
||||||
if (!XFilterEvent(&windowEvent, None))
|
|
||||||
|
// Generate a KeyPressed event if needed
|
||||||
|
if (filtered)
|
||||||
|
{
|
||||||
|
pushEvent(event);
|
||||||
|
isKeyFiltered.set(windowEvent.xkey.keycode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Push a KeyPressed event if the key has never been filtered before
|
||||||
|
// (a KeyPressed event would have already been pushed if it had been filtered).
|
||||||
|
//
|
||||||
|
// Some dummy IMs (like the built-in one you get by setting XMODIFIERS=@im=none)
|
||||||
|
// never filter events away, and we have to take care of that.
|
||||||
|
//
|
||||||
|
// In addition, ignore text-only KeyPress events generated by IMs (with keycode set to 0).
|
||||||
|
if (!isKeyFiltered.test(windowEvent.xkey.keycode) && windowEvent.xkey.keycode != 0)
|
||||||
|
pushEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate TextEntered events if needed
|
||||||
|
if (!filtered)
|
||||||
{
|
{
|
||||||
#ifdef X_HAVE_UTF8_STRING
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
if (m_inputContext)
|
if (m_inputContext)
|
||||||
|
@ -297,16 +297,15 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
::Window m_window; ///< X identifier defining our window
|
::Window m_window; ///< X identifier defining our window
|
||||||
::Display* m_display; ///< Pointer to the display
|
::Display* m_display; ///< Pointer to the display
|
||||||
int m_screen; ///< Screen identifier
|
int m_screen; ///< Screen identifier
|
||||||
XIM m_inputMethod; ///< Input method linked to the X display
|
XIM m_inputMethod; ///< Input method linked to the X display
|
||||||
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
||||||
std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
|
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
RRMode m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
||||||
RRMode m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
RRCrtc m_oldRRCrtc; ///< RRCrtc in use before we switch to fullscreen
|
||||||
RRCrtc m_oldRRCrtc; ///< RRCrtc in use before we switch to fullscreen
|
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
||||||
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
|
||||||
::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
|
::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
|
||||||
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
||||||
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
|
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
|
||||||
|
Loading…
Reference in New Issue
Block a user