mirror of
https://github.com/SFML/SFML.git
synced 2024-12-01 07:41:05 +08:00
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: 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: MacOS, os: macos-latest }
|
||||
- { name: MacOS Xcode, os: macos-latest, flags: -GXcode }
|
||||
- { name: MacOS, os: macos-11 }
|
||||
- { name: MacOS Xcode, os: macos-11, flags: -GXcode }
|
||||
config:
|
||||
- { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE }
|
||||
- { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE }
|
||||
@ -34,9 +34,9 @@ jobs:
|
||||
- platform: { name: Windows VS2022, os: windows-2022 }
|
||||
config: { name: Unity, flags: -DBUILD_SHARED_LIBS=TRUE -DCMAKE_UNITY_BUILD=ON }
|
||||
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 }
|
||||
- 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 }
|
||||
- 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 }
|
||||
|
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
static int find_drm_device(drmModeRes **resources)
|
||||
@ -199,7 +219,11 @@ static int find_drm_device(drmModeRes **resources)
|
||||
if (fd < 0)
|
||||
continue;
|
||||
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;
|
||||
close(fd);
|
||||
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");
|
||||
}
|
||||
|
||||
/* 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: */
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
@ -91,14 +91,18 @@ void cleanup()
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
drmModeSetCrtc(drmNode.fd,
|
||||
drmNode.original_crtc->crtc_id,
|
||||
drmNode.original_crtc->buffer_id,
|
||||
drmNode.original_crtc->x,
|
||||
drmNode.original_crtc->y,
|
||||
&drmNode.connector_id,
|
||||
1,
|
||||
&drmNode.original_crtc->mode);
|
||||
/* Avoid a modeswitch if possible */
|
||||
if (drmNode.mode != &drmNode.original_crtc->mode)
|
||||
drmModeSetCrtc(drmNode.fd,
|
||||
drmNode.original_crtc->crtc_id,
|
||||
drmNode.original_crtc->buffer_id,
|
||||
drmNode.original_crtc->x,
|
||||
drmNode.original_crtc->y,
|
||||
&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);
|
||||
drmModeFreeEncoder(drmNode.saved_encoder);
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
@ -77,6 +78,7 @@ namespace WindowsImplX11Impl
|
||||
{
|
||||
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
|
||||
std::vector<sf::priv::WindowImplX11*> allWindows;
|
||||
std::bitset<256> isKeyFiltered;
|
||||
std::recursive_mutex allWindowsMutex;
|
||||
sf::String windowManagerName;
|
||||
|
||||
@ -88,23 +90,6 @@ constexpr unsigned long eventMask = FocusChangeMask | ButtonPressMask | ButtonRe
|
||||
|
||||
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)
|
||||
Bool checkEvent(::Display*, XEvent* event, XPointer userData)
|
||||
{
|
||||
@ -831,14 +816,61 @@ void WindowImplX11::processEvents()
|
||||
|
||||
// Pick out the events that are interesting for this 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();
|
||||
m_events.pop_front();
|
||||
processEvent(event);
|
||||
// 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 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
|
||||
@ -1731,33 +1763,6 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
||||
{
|
||||
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
|
||||
switch (windowEvent.type)
|
||||
{
|
||||
@ -1913,10 +1918,30 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
||||
event.key.control = windowEvent.xkey.state & ControlMask;
|
||||
event.key.shift = windowEvent.xkey.state & ShiftMask;
|
||||
event.key.system = windowEvent.xkey.state & Mod4Mask;
|
||||
pushEvent(event);
|
||||
|
||||
// Generate a TextEntered event
|
||||
if (!XFilterEvent(&windowEvent, None))
|
||||
const bool filtered = 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
|
||||
if (m_inputContext)
|
||||
|
@ -297,16 +297,15 @@ private:
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
::Window m_window; ///< X identifier defining our window
|
||||
::Display* m_display; ///< Pointer to the display
|
||||
int m_screen; ///< Screen identifier
|
||||
XIM m_inputMethod; ///< Input method linked to the X display
|
||||
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
|
||||
RRMode m_oldVideoMode; ///< Video mode 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
|
||||
::Window m_window; ///< X identifier defining our window
|
||||
::Display* m_display; ///< Pointer to the display
|
||||
int m_screen; ///< Screen identifier
|
||||
XIM m_inputMethod; ///< Input method linked to the X display
|
||||
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
||||
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
|
||||
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_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?
|
||||
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