mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-23 18:53:08 +08:00
Up-to-date QNX support (#14806)
Co-authored-by: Roberto Speranza <rsperanza@qnx.com> Co-authored-by: Darcy Phipps <dphipps@qnx.com> Co-authored-by: Pierce McKinnon <pimckinnon@qnx.com>
This commit is contained in:
@@ -1813,7 +1813,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
||||
"${SDL3_SOURCE_DIR}/src/audio/netbsd/*.h"
|
||||
)
|
||||
set(HAVE_SDL_AUDIO TRUE)
|
||||
elseif(QNX)
|
||||
elseif(QNX AND (CMAKE_SYSTEM_VERSION VERSION_LESS "8.0.0"))
|
||||
set(SDL_AUDIO_DRIVER_QNX 1)
|
||||
sdl_glob_sources(
|
||||
"${SDL3_SOURCE_DIR}/src/audio/qnx/*.c"
|
||||
|
||||
44
docs/README-qnx.md
Normal file
44
docs/README-qnx.md
Normal file
@@ -0,0 +1,44 @@
|
||||
QNX
|
||||
=======
|
||||
|
||||
SDL port for QNX, providing both screen and Wayland video backends.
|
||||
|
||||
This was originally contributed by Elad Lahav for QNX 7.0.
|
||||
|
||||
The port was later improved and adapted for QNX 8.0 by:
|
||||
- Ethan Leir
|
||||
- Roberto Speranza
|
||||
- Darcy Phipps
|
||||
- Jai Moraes
|
||||
- Pierce McKinnon
|
||||
|
||||
Further changes to enable Wayland with the EGL backend were made by Felix Xing
|
||||
and Aaron Bassett.
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
Building SDL3 for QNX requires Wayland to be built and installed. The commands
|
||||
to build it are,
|
||||
```bash
|
||||
# Note, if you're cross-compiling, you will need to source qnxsdp-env.sh and
|
||||
# provide the path to a cmake toolchain file with -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_DIR/qnx.nto.toolchain.cmake
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DSDL_X11=0
|
||||
cmake --build build
|
||||
cmake --install build
|
||||
```
|
||||
|
||||
## QNX self-hosted
|
||||
|
||||
QNX provides a self-hosted environment, available with [the free license](https://www.qnx.com/products/everywhere/).
|
||||
This is the easiest way to get your hands on SDL.
|
||||
|
||||
## QNX build-files
|
||||
|
||||
You can find the cross-compiled build tools at https://github.com/qnx-ports/build-files
|
||||
|
||||
## Notes - screen
|
||||
|
||||
- Currently, only software and OpenGLES2 rendering is supported.
|
||||
- Unless your application is managed by a window manager capable of closing the application, you will need to quit it yourself.
|
||||
- Restraining the mouse to a window or warping the mouse cursor will not work.
|
||||
@@ -277,7 +277,7 @@
|
||||
#define SDL_PLATFORM_OSF 1
|
||||
#endif
|
||||
|
||||
#ifdef __QNXNTO__
|
||||
#if defined(__QNXNTO__) || defined(__QNX__)
|
||||
|
||||
/**
|
||||
* A preprocessor macro that is only defined if compiling for QNX Neutrino.
|
||||
|
||||
@@ -1560,6 +1560,13 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window)
|
||||
* - `SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER`: the OpenVR Overlay Handle ID
|
||||
* for the associated overlay window.
|
||||
*
|
||||
* On QNX:
|
||||
*
|
||||
* - `SDL_PROP_WINDOW_QNX_WINDOW_POINTER`: the screen_window_t associated with
|
||||
* the window.
|
||||
* - `SDL_PROP_WINDOW_QNX_SURFACE_POINTER`: the EGLSurface associated with
|
||||
* the window
|
||||
*
|
||||
* On Vivante:
|
||||
*
|
||||
* - `SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER`: the EGLNativeDisplayType
|
||||
@@ -1644,6 +1651,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window
|
||||
#define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window"
|
||||
#define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag"
|
||||
#define SDL_PROP_WINDOW_OPENVR_OVERLAY_ID_NUMBER "SDL.window.openvr.overlay_id"
|
||||
#define SDL_PROP_WINDOW_QNX_WINDOW_POINTER "SDL.window.qnx.window"
|
||||
#define SDL_PROP_WINDOW_QNX_SURFACE_POINTER "SDL.window.qnx.surface"
|
||||
#define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display"
|
||||
#define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window"
|
||||
#define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface"
|
||||
|
||||
@@ -252,7 +252,12 @@ bool SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
sched.sched_priority = sched_get_priority_min(policy);
|
||||
} else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
|
||||
#if defined(__QNX__)
|
||||
/* io_snd complains about a client thread having priority >= 49 */
|
||||
sched.sched_priority = 48;
|
||||
#else
|
||||
sched.sched_priority = sched_get_priority_max(policy);
|
||||
#endif
|
||||
} else {
|
||||
int min_priority = sched_get_priority_min(policy);
|
||||
int max_priority = sched_get_priority_max(policy);
|
||||
|
||||
@@ -102,6 +102,13 @@
|
||||
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
|
||||
#define DEFAULT_OGL_ES "libGLESv1_CM.so"
|
||||
|
||||
#elif defined(SDL_VIDEO_DRIVER_QNX)
|
||||
// QNX
|
||||
#define DEFAULT_EGL "libEGL.so.1"
|
||||
#define DEFAULT_OGL_ES2 "libGLESv2.so.1"
|
||||
#define DEFAULT_OGL_ES_PVR "libGLESv2.so.1"
|
||||
#define DEFAULT_OGL_ES "libGLESv2.so.1"
|
||||
|
||||
#else
|
||||
// Desktop Linux/Unix-like
|
||||
#define DEFAULT_OGL "libGL.so.1"
|
||||
|
||||
@@ -279,7 +279,7 @@ typedef struct
|
||||
|
||||
static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this)
|
||||
{
|
||||
#if (defined(SDL_VIDEO_OPENGL) && defined(SDL_PLATFORM_MACOS)) || (defined(SDL_PLATFORM_IOS) && !TARGET_OS_MACCATALYST)
|
||||
#if (defined(SDL_VIDEO_OPENGL) && defined(SDL_PLATFORM_MACOS)) || (defined(SDL_PLATFORM_IOS) && !TARGET_OS_MACCATALYST) || defined(SDL_PLATFORM_QNXNTO)
|
||||
if (_this->GL_CreateContext) {
|
||||
return SDL_WINDOW_OPENGL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2017 BlackBerry Limited
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -26,23 +26,62 @@
|
||||
#include <screen/screen.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct
|
||||
typedef struct SDL_DisplayData
|
||||
{
|
||||
screen_display_t screen_display;
|
||||
} SDL_DisplayData;
|
||||
|
||||
typedef struct SDL_DisplayModeData
|
||||
{
|
||||
int screen_format;
|
||||
screen_display_mode_t screen_display_mode;
|
||||
} SDL_DisplayModeData;
|
||||
|
||||
typedef struct SDL_WindowData
|
||||
{
|
||||
screen_window_t window;
|
||||
EGLSurface surface;
|
||||
EGLConfig conf;
|
||||
} window_impl_t;
|
||||
SDL_GLContext context;
|
||||
int resize;
|
||||
bool has_focus;
|
||||
} SDL_WindowData;
|
||||
|
||||
typedef struct SDL_CursorData
|
||||
{
|
||||
screen_session_t session;
|
||||
int realized_shape;
|
||||
bool is_visible;
|
||||
} SDL_CursorData;
|
||||
|
||||
typedef struct SDL_MouseData
|
||||
{
|
||||
int x_prev;
|
||||
int y_prev;
|
||||
} SDL_MouseData;
|
||||
|
||||
extern screen_context_t * getContext();
|
||||
extern screen_event_t * getEvent();
|
||||
|
||||
extern void handleKeyboardEvent(screen_event_t event);
|
||||
extern void handlePointerEvent(screen_event_t event);
|
||||
|
||||
extern bool glGetConfig(EGLConfig *pconf, int *pformat);
|
||||
extern bool glInitConfig(SDL_WindowData *impl, int *pformat);
|
||||
extern bool glLoadLibrary(SDL_VideoDevice *_this, const char *name);
|
||||
extern SDL_FunctionPointer glGetProcAddress(SDL_VideoDevice *_this, const char *proc);
|
||||
extern SDL_GLContext glCreateContext(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern bool glSetSwapInterval(SDL_VideoDevice *_this, int interval);
|
||||
extern bool glSwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern bool glMakeCurrent(SDL_VideoDevice *_this, SDL_Window * window, SDL_GLContext context);
|
||||
extern void glDeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
extern bool glDeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
|
||||
extern void glUnloadLibrary(SDL_VideoDevice *_this);
|
||||
|
||||
extern SDL_PixelFormat screenToPixelFormat(int screen_format);
|
||||
extern bool getDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
|
||||
extern bool setDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
||||
extern bool getDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
|
||||
extern void initMouse(SDL_VideoDevice *_this);
|
||||
extern void quitMouse(SDL_VideoDevice *_this);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2017 BlackBerry Limited
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,11 +19,119 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_qnx.h"
|
||||
|
||||
static EGLDisplay egl_disp;
|
||||
|
||||
struct DummyConfig
|
||||
{
|
||||
int red_size;
|
||||
int green_size;
|
||||
int blue_size;
|
||||
int alpha_size;
|
||||
int native_id;
|
||||
};
|
||||
|
||||
static struct DummyConfig getDummyConfigFromScreenSettings(int format)
|
||||
{
|
||||
struct DummyConfig dummyConfig= {};
|
||||
|
||||
dummyConfig.native_id = format;
|
||||
switch (format) {
|
||||
case SCREEN_FORMAT_RGBX4444:
|
||||
dummyConfig.red_size = 4;
|
||||
dummyConfig.green_size = 4;
|
||||
dummyConfig.blue_size = 4;
|
||||
dummyConfig.alpha_size = 4;
|
||||
break;
|
||||
case SCREEN_FORMAT_RGBA5551:
|
||||
dummyConfig.red_size = 5;
|
||||
dummyConfig.green_size = 5;
|
||||
dummyConfig.blue_size = 5;
|
||||
dummyConfig.alpha_size = 1;
|
||||
break;
|
||||
case SCREEN_FORMAT_RGB565:
|
||||
dummyConfig.red_size = 5;
|
||||
dummyConfig.green_size = 6;
|
||||
dummyConfig.blue_size = 5;
|
||||
dummyConfig.alpha_size = 0;
|
||||
break;
|
||||
case SCREEN_FORMAT_RGB888:
|
||||
dummyConfig.red_size = 8;
|
||||
dummyConfig.green_size = 8;
|
||||
dummyConfig.blue_size = 8;
|
||||
dummyConfig.alpha_size = 0;
|
||||
break;
|
||||
case SCREEN_FORMAT_BGRA8888:
|
||||
case SCREEN_FORMAT_BGRX8888:
|
||||
case SCREEN_FORMAT_RGBA8888:
|
||||
case SCREEN_FORMAT_RGBX8888:
|
||||
dummyConfig.red_size = 8;
|
||||
dummyConfig.green_size = 8;
|
||||
dummyConfig.blue_size = 8;
|
||||
dummyConfig.alpha_size = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return dummyConfig;
|
||||
}
|
||||
|
||||
static EGLConfig chooseConfig(struct DummyConfig dummyConfig, EGLConfig* egl_configs, EGLint egl_num_configs)
|
||||
{
|
||||
EGLConfig glConfig = (EGLConfig)0;
|
||||
|
||||
for (size_t ii = 0; ii < egl_num_configs; ii++) {
|
||||
EGLint val;
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_SURFACE_TYPE, &val);
|
||||
if (!(val & EGL_WINDOW_BIT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_RENDERABLE_TYPE, &val);
|
||||
if (!(val & EGL_OPENGL_ES2_BIT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_DEPTH_SIZE, &val);
|
||||
if (val == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_RED_SIZE, &val);
|
||||
if (val != dummyConfig.red_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_GREEN_SIZE, &val);
|
||||
if (val != dummyConfig.green_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_BLUE_SIZE, &val);
|
||||
if (val != dummyConfig.blue_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_ALPHA_SIZE, &val);
|
||||
if (val != dummyConfig.alpha_size) {
|
||||
continue;
|
||||
}
|
||||
if(!glConfig)
|
||||
{
|
||||
glConfig = egl_configs[ii];
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[ii], EGL_NATIVE_VISUAL_ID, &val);
|
||||
if ((val != 0) && (val == dummyConfig.native_id)) {
|
||||
return egl_configs[ii];
|
||||
}
|
||||
}
|
||||
return glConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detertmines the pixel format to use based on the current display and EGL
|
||||
* configuration.
|
||||
@@ -42,7 +150,7 @@ static int chooseFormat(EGLConfig egl_conf)
|
||||
case 32:
|
||||
return SCREEN_FORMAT_RGBX8888;
|
||||
case 24:
|
||||
return SDL_PIXELFORMAT_RGB24;
|
||||
return SCREEN_FORMAT_RGB888;
|
||||
case 16:
|
||||
switch (alpha_bit_depth) {
|
||||
case 4:
|
||||
@@ -59,20 +167,18 @@ static int chooseFormat(EGLConfig egl_conf)
|
||||
|
||||
/**
|
||||
* Enumerates the supported EGL configurations and chooses a suitable one.
|
||||
* @param[out] pconf The chosen configuration
|
||||
* @param[out] pformat The chosen pixel format
|
||||
* @return true if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
bool glGetConfig(EGLConfig *pconf, int *pformat)
|
||||
bool glInitConfig(SDL_WindowData *impl, int *pformat)
|
||||
{
|
||||
EGLConfig egl_conf = (EGLConfig)0;
|
||||
EGLConfig *egl_configs;
|
||||
EGLint egl_num_configs;
|
||||
EGLint val;
|
||||
EGLBoolean rc;
|
||||
EGLint i;
|
||||
struct DummyConfig dummyconfig = {};
|
||||
|
||||
// Determine the numbfer of configurations.
|
||||
// Determine the number of configurations.
|
||||
rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
|
||||
if (rc != EGL_TRUE) {
|
||||
return false;
|
||||
@@ -96,30 +202,12 @@ bool glGetConfig(EGLConfig *pconf, int *pformat)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find a good configuration.
|
||||
for (i = 0; i < egl_num_configs; i++) {
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
|
||||
if (!(val & EGL_WINDOW_BIT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
|
||||
if (!(val & EGL_OPENGL_ES2_BIT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
|
||||
if (val == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
egl_conf = egl_configs[i];
|
||||
break;
|
||||
}
|
||||
dummyconfig = getDummyConfigFromScreenSettings(*pformat);
|
||||
egl_conf = chooseConfig(dummyconfig, egl_configs, egl_num_configs);
|
||||
*pformat = chooseFormat(egl_conf);
|
||||
|
||||
SDL_free(egl_configs);
|
||||
*pconf = egl_conf;
|
||||
*pformat = chooseFormat(egl_conf);
|
||||
impl->conf = egl_conf;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -128,7 +216,7 @@ bool glGetConfig(EGLConfig *pconf, int *pformat)
|
||||
* Initializes the EGL library.
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param name unused
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
bool glLoadLibrary(SDL_VideoDevice *_this, const char *name)
|
||||
{
|
||||
@@ -165,7 +253,7 @@ SDL_FunctionPointer glGetProcAddress(SDL_VideoDevice *_this, const char *proc)
|
||||
*/
|
||||
SDL_GLContext glCreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
EGLContext context;
|
||||
EGLSurface surface;
|
||||
|
||||
@@ -201,6 +289,10 @@ SDL_GLContext glCreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
eglMakeCurrent(egl_disp, surface, surface, context);
|
||||
|
||||
impl->surface = surface;
|
||||
impl->context = context;
|
||||
|
||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_QNX_SURFACE_POINTER, impl->surface);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -208,7 +300,7 @@ SDL_GLContext glCreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
* Sets a new value for the number of frames to display before swapping buffers.
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param interval New interval value
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
bool glSetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
{
|
||||
@@ -223,13 +315,44 @@ bool glSetSwapInterval(SDL_VideoDevice *_this, int interval)
|
||||
* Swaps the EGL buffers associated with the given window
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param window Window to swap buffers for
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
bool glSwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
// !!! FIXME: should we migrate this all over to use SDL_egl.c?
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
return eglSwapBuffers(egl_disp, impl->surface) == EGL_TRUE ? 0 : -1;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
{
|
||||
if (impl->resize) {
|
||||
EGLSurface surface;
|
||||
struct {
|
||||
EGLint render_buffer[2];
|
||||
EGLint none;
|
||||
} egl_surf_attr = {
|
||||
.render_buffer = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER },
|
||||
.none = EGL_NONE
|
||||
};
|
||||
|
||||
if (eglMakeCurrent(egl_disp, NULL, NULL, impl->context) != EGL_TRUE) {
|
||||
return false;
|
||||
}
|
||||
eglDestroySurface(egl_disp, impl->surface);
|
||||
|
||||
surface = eglCreateWindowSurface(egl_disp, impl->conf, impl->window,
|
||||
(EGLint *)&egl_surf_attr);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eglMakeCurrent(egl_disp, surface, surface, impl->context) != EGL_TRUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl->surface = surface;
|
||||
impl->resize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return eglSwapBuffers(egl_disp, impl->surface) == EGL_TRUE ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,15 +360,15 @@ bool glSwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param window SDL window associated with the context (maybe NULL)
|
||||
* @param context The context to activate
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
bool glMakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
|
||||
{
|
||||
window_impl_t *impl;
|
||||
SDL_WindowData *impl;
|
||||
EGLSurface surface = NULL;
|
||||
|
||||
if (window) {
|
||||
impl = (window_impl_t *)window->internal;
|
||||
impl = (SDL_WindowData *)window->internal;
|
||||
surface = impl->surface;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2017 BlackBerry Limited
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -19,7 +19,7 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_internal.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "SDL3/SDL_scancode.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
@@ -84,10 +84,81 @@ static int key_to_sdl[] = {
|
||||
[KEYCODE_LEFT] = SDL_SCANCODE_LEFT,
|
||||
[KEYCODE_PG_UP] = SDL_SCANCODE_PAGEUP,
|
||||
[KEYCODE_PG_DOWN] = SDL_SCANCODE_PAGEDOWN,
|
||||
[KEYCODE_PRINT] = SDL_SCANCODE_PRINTSCREEN,
|
||||
[KEYCODE_SCROLL_LOCK] = SDL_SCANCODE_SCROLLLOCK,
|
||||
[KEYCODE_PAUSE] = SDL_SCANCODE_PAUSE,
|
||||
[KEYCODE_INSERT] = SDL_SCANCODE_INSERT,
|
||||
[KEYCODE_HOME] = SDL_SCANCODE_HOME,
|
||||
[KEYCODE_DELETE] = SDL_SCANCODE_DELETE,
|
||||
[KEYCODE_END] = SDL_SCANCODE_END,
|
||||
[KEYCODE_NUM_LOCK] = SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
[KEYCODE_RIGHT] = SDL_SCANCODE_RIGHT,
|
||||
[KEYCODE_RETURN] = SDL_SCANCODE_RETURN,
|
||||
[KEYCODE_TAB] = SDL_SCANCODE_TAB,
|
||||
[KEYCODE_ESCAPE] = SDL_SCANCODE_ESCAPE,
|
||||
[KEYCODE_LEFT_CTRL] = SDL_SCANCODE_LCTRL,
|
||||
[KEYCODE_RIGHT_CTRL] = SDL_SCANCODE_RCTRL,
|
||||
[KEYCODE_LEFT_SHIFT] = SDL_SCANCODE_LSHIFT,
|
||||
[KEYCODE_RIGHT_SHIFT] = SDL_SCANCODE_RSHIFT,
|
||||
[KEYCODE_LEFT_ALT] = SDL_SCANCODE_LALT,
|
||||
[KEYCODE_RIGHT_ALT] = SDL_SCANCODE_RALT,
|
||||
[KEYCODE_BACKSPACE] = SDL_SCANCODE_BACKSPACE,
|
||||
[KEYCODE_CAPS_LOCK] = SDL_SCANCODE_CAPSLOCK,
|
||||
[KEYCODE_F1] = SDL_SCANCODE_F1,
|
||||
[KEYCODE_F2] = SDL_SCANCODE_F2,
|
||||
[KEYCODE_F3] = SDL_SCANCODE_F3,
|
||||
[KEYCODE_F4] = SDL_SCANCODE_F4,
|
||||
[KEYCODE_F5] = SDL_SCANCODE_F5,
|
||||
[KEYCODE_F6] = SDL_SCANCODE_F6,
|
||||
[KEYCODE_F7] = SDL_SCANCODE_F7,
|
||||
[KEYCODE_F8] = SDL_SCANCODE_F8,
|
||||
[KEYCODE_F9] = SDL_SCANCODE_F9,
|
||||
[KEYCODE_F10] = SDL_SCANCODE_F10,
|
||||
[KEYCODE_F11] = SDL_SCANCODE_F11,
|
||||
[KEYCODE_F12] = SDL_SCANCODE_F12,
|
||||
[KEYCODE_KP_DIVIDE] = SDL_SCANCODE_KP_DIVIDE,
|
||||
[KEYCODE_KP_MULTIPLY] = SDL_SCANCODE_KP_MULTIPLY,
|
||||
[KEYCODE_KP_MINUS] = SDL_SCANCODE_KP_MINUS,
|
||||
[KEYCODE_KP_PLUS] = SDL_SCANCODE_KP_PLUS,
|
||||
[KEYCODE_KP_ENTER] = SDL_SCANCODE_KP_ENTER,
|
||||
/* NO SCREEN MAPPING FOR KEYPAD DIGITS
|
||||
[KEYCODE_ZERO] = SDL_SCANCODE_KP_0,
|
||||
[KEYCODE_ONE] = SDL_SCANCODE_KP_1,
|
||||
[KEYCODE_TWO] = SDL_SCANCODE_KP_2,
|
||||
[KEYCODE_THREE] = SDL_SCANCODE_KP_3,
|
||||
[KEYCODE_FOUR] = SDL_SCANCODE_KP_4,
|
||||
[KEYCODE_FIVE] = SDL_SCANCODE_KP_5,
|
||||
[KEYCODE_SIX] = SDL_SCANCODE_KP_6,
|
||||
[KEYCODE_SEVEN] = SDL_SCANCODE_KP_7,
|
||||
[KEYCODE_EIGHT] = SDL_SCANCODE_KP_8,
|
||||
[KEYCODE_NINE] = SDL_SCANCODE_KP_9,
|
||||
[KEYCODE_PERIOD] = SDL_SCANCODE_KP_PERIOD,
|
||||
*/
|
||||
[KEYCODE_POWER] = SDL_SCANCODE_POWER,
|
||||
[KEYCODE_PLAY] = SDL_SCANCODE_EXECUTE,
|
||||
[KEYCODE_HELP] = SDL_SCANCODE_HELP,
|
||||
[KEYCODE_MENU] = SDL_SCANCODE_MENU,
|
||||
[KEYCODE_AC_SELECT_ALL] = SDL_SCANCODE_SELECT,
|
||||
[KEYCODE_STOP] = SDL_SCANCODE_STOP,
|
||||
[KEYCODE_AC_UNDO] = SDL_SCANCODE_UNDO,
|
||||
[KEYCODE_AC_CUT] = SDL_SCANCODE_CUT,
|
||||
[KEYCODE_AC_COPY] = SDL_SCANCODE_COPY,
|
||||
[KEYCODE_AC_PASTE] = SDL_SCANCODE_PASTE,
|
||||
[KEYCODE_AC_FIND] = SDL_SCANCODE_FIND,
|
||||
[KEYCODE_MUTE] = SDL_SCANCODE_MUTE,
|
||||
[KEYCODE_VOLUME_UP] = SDL_SCANCODE_VOLUMEUP,
|
||||
[KEYCODE_VOLUME_DOWN] = SDL_SCANCODE_VOLUMEDOWN,
|
||||
[KEYCODE_SYSREQ] = SDL_SCANCODE_SYSREQ,
|
||||
[KEYCODE_AC_CANCEL] = SDL_SCANCODE_CANCEL,
|
||||
[KEYCODE_AC_SEARCH] = SDL_SCANCODE_AC_SEARCH,
|
||||
[KEYCODE_AC_HOME] = SDL_SCANCODE_AC_HOME,
|
||||
[KEYCODE_AC_BACK] = SDL_SCANCODE_AC_BACK,
|
||||
[KEYCODE_AC_FORWARD] = SDL_SCANCODE_AC_FORWARD,
|
||||
[KEYCODE_AC_STOP] = SDL_SCANCODE_AC_STOP,
|
||||
[KEYCODE_AC_REFRESH] = SDL_SCANCODE_AC_REFRESH,
|
||||
[KEYCODE_AC_BOOKMARKS] = SDL_SCANCODE_AC_BOOKMARKS,
|
||||
[KEYCODE_EJECT] = SDL_SCANCODE_MEDIA_EJECT,
|
||||
[KEYCODE_SLEEP] = SDL_SCANCODE_SLEEP,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -98,6 +169,8 @@ static int key_to_sdl[] = {
|
||||
void handleKeyboardEvent(screen_event_t event)
|
||||
{
|
||||
int val;
|
||||
int cap;
|
||||
char ascii_text[2];
|
||||
SDL_Scancode scancode;
|
||||
|
||||
// Get the key value.
|
||||
@@ -105,6 +178,10 @@ void handleKeyboardEvent(screen_event_t event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip unrecognized keys.
|
||||
if ((val < 0) || (val >= SDL_arraysize(key_to_sdl))) {
|
||||
return;
|
||||
@@ -126,6 +203,17 @@ void handleKeyboardEvent(screen_event_t event)
|
||||
// Need to handle more key states (such as key combinations).
|
||||
if (val & KEY_DOWN) {
|
||||
SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, val, scancode, true);
|
||||
|
||||
// TODO: To simplify, we're ignoring keycodes that aren't just ascii.
|
||||
if ((val < UNICODE_PRIVATE_USE_AREA_FIRST) && ((cap & 0xFF) == cap)) {
|
||||
ascii_text[0] = cap;
|
||||
ascii_text[1] = 0;
|
||||
SDL_SendKeyboardText(ascii_text);
|
||||
} else if ((KEYCODE_PC_KEYS <= val) && (val < KEYCODE_CONSUMER_KEYS)) {
|
||||
ascii_text[0] = val & 0xFF;
|
||||
ascii_text[1] = 0;
|
||||
SDL_SendKeyboardText(ascii_text);
|
||||
}
|
||||
} else {
|
||||
SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, val, scancode, false);
|
||||
}
|
||||
|
||||
195
src/video/qnx/SDL_qnxmodes.c
Normal file
195
src/video/qnx/SDL_qnxmodes.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "SDL_qnx.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
// All indices not already assigned will be zero'd to SDL_PIXELFORMAT_UNKNOWN.
|
||||
static const SDL_PixelFormat _format_map[] = {
|
||||
[SCREEN_FORMAT_RGBA4444] = SDL_PIXELFORMAT_RGBA4444,
|
||||
[SCREEN_FORMAT_RGBA5551] = SDL_PIXELFORMAT_RGBA5551,
|
||||
[SCREEN_FORMAT_RGB565] = SDL_PIXELFORMAT_RGB565,
|
||||
[SCREEN_FORMAT_RGBA8888] = SDL_PIXELFORMAT_RGBA8888,
|
||||
[SCREEN_FORMAT_RGBX8888] = SDL_PIXELFORMAT_RGBX8888,
|
||||
[SCREEN_FORMAT_NV12] = SDL_PIXELFORMAT_NV12,
|
||||
[SCREEN_FORMAT_YV12] = SDL_PIXELFORMAT_YV12,
|
||||
[SCREEN_FORMAT_UYVY] = SDL_PIXELFORMAT_UYVY,
|
||||
[SCREEN_FORMAT_YUY2] = SDL_PIXELFORMAT_YUY2,
|
||||
[SCREEN_FORMAT_YVYU] = SDL_PIXELFORMAT_YVYU,
|
||||
[SCREEN_FORMAT_P010] = SDL_PIXELFORMAT_P010,
|
||||
[SCREEN_FORMAT_BGRA8888] = SDL_PIXELFORMAT_BGRA8888,
|
||||
[SCREEN_FORMAT_BGRX8888] = SDL_PIXELFORMAT_BGRX8888,
|
||||
};
|
||||
|
||||
SDL_PixelFormat screenToPixelFormat(int screen_format)
|
||||
{
|
||||
if ((screen_format < 0) || (screen_format >= SDL_arraysize(_format_map))) {
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
return _format_map[screen_format];
|
||||
}
|
||||
|
||||
bool getDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
|
||||
{
|
||||
SDL_DisplayData *display_data = display->internal;
|
||||
SDL_DisplayMode display_mode;
|
||||
SDL_DisplayModeData *display_mode_data;
|
||||
|
||||
int index;
|
||||
int display_mode_count;
|
||||
|
||||
screen_display_t screen_display;
|
||||
screen_display_mode_t *screen_display_modes;
|
||||
int screen_format;
|
||||
int screen_refresh_rate;
|
||||
|
||||
if (display_data == NULL) {
|
||||
return false;
|
||||
}
|
||||
screen_display = display_data->screen_display;
|
||||
|
||||
/* create SDL display imodes based on display mode info from the display */
|
||||
if (screen_get_display_property_iv(screen_display, SCREEN_PROPERTY_MODE_COUNT, &display_mode_count) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
screen_display_modes = SDL_calloc(display_mode_count, sizeof(screen_display_mode_t));
|
||||
if (screen_display_modes == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(screen_get_display_modes(screen_display, display_mode_count, screen_display_modes) < 0) {
|
||||
SDL_free(screen_display_modes);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (index = 0; index < display_mode_count; index++) {
|
||||
display_mode_data = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (display_mode_data == NULL) {
|
||||
// Not much we can do about the objs we've already created at this point.
|
||||
SDL_free(screen_display_modes);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_zero(display_mode);
|
||||
display_mode.w = screen_display_modes[index].width;
|
||||
display_mode.h = screen_display_modes[index].height;
|
||||
display_mode.pixel_density = 1.0;
|
||||
display_mode.internal = display_mode_data;
|
||||
|
||||
if (screen_display_modes[index].flags & SCREEN_DISPLAY_MODE_REFRESH_VALID) {
|
||||
screen_refresh_rate = screen_display_modes[index].refresh;
|
||||
} else {
|
||||
// Fallback
|
||||
screen_refresh_rate = 60;
|
||||
}
|
||||
if (screen_display_modes[index].flags & SCREEN_DISPLAY_MODE_FORMAT_VALID) {
|
||||
screen_format = screen_display_modes[index].format;
|
||||
} else {
|
||||
// Fallback
|
||||
screen_format = SCREEN_FORMAT_RGBX8888;
|
||||
}
|
||||
display_mode.refresh_rate = screen_refresh_rate;
|
||||
display_mode.format = screenToPixelFormat(screen_format);
|
||||
display_mode_data->screen_format = screen_format;
|
||||
display_mode_data->screen_display_mode = screen_display_modes[index];
|
||||
|
||||
// This op can fail if the mode already exists.
|
||||
SDL_AddFullscreenDisplayMode(display, &display_mode);
|
||||
}
|
||||
|
||||
SDL_free(screen_display_modes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// FIXME: This seems to invalidate the screen_display_t, causing issues with the
|
||||
// (get|set)_display_property_*() apis. For now, mode switching is emulated
|
||||
// instead.
|
||||
bool setDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayData *display_data = display->internal;
|
||||
SDL_DisplayModeData *display_mode_data = mode->internal;
|
||||
|
||||
if ((display_data == NULL) || (display_mode_data == NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: May need to call glInitConfig and screen_create_window_buffers.
|
||||
if (screen_set_display_property_iv(display_data->screen_display,
|
||||
SCREEN_PROPERTY_MODE, (int *)&display_mode_data->screen_display_mode.index) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
SDL_DisplayData *data = display->internal;
|
||||
int size[2] = { 0, 0 };
|
||||
|
||||
if (data == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (screen_get_display_property_iv(data->screen_display, SCREEN_PROPERTY_SIZE, size) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
rect->w = size[0];
|
||||
rect->h = size[1];
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool getDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
if (display->current_mode == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
|
||||
// When an emulated, exclusive fullscreen window has focus, treat the mode dimensions as the display bounds.
|
||||
if (display->fullscreen_window &&
|
||||
display->fullscreen_window->fullscreen_exclusive &&
|
||||
display->fullscreen_window->current_fullscreen_mode.w != 0 &&
|
||||
display->fullscreen_window->current_fullscreen_mode.h != 0) {
|
||||
rect->w = display->fullscreen_window->current_fullscreen_mode.w;
|
||||
rect->h = display->fullscreen_window->current_fullscreen_mode.h;
|
||||
} else {
|
||||
rect->w = display->current_mode->w;
|
||||
rect->h = display->current_mode->h;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
189
src/video/qnx/SDL_qnxmouse.c
Normal file
189
src/video/qnx/SDL_qnxmouse.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "SDL_qnx.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static int SDLToScreenCursorShape(SDL_SystemCursor id)
|
||||
{
|
||||
// This is reserved by screen, but still not used for anything.
|
||||
int shape = -1;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case SDL_SYSTEM_CURSOR_DEFAULT:
|
||||
case SDL_SYSTEM_CURSOR_NOT_ALLOWED:
|
||||
shape = SCREEN_CURSOR_SHAPE_ARROW;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_TEXT:
|
||||
shape = SCREEN_CURSOR_SHAPE_IBEAM;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT:
|
||||
shape = SCREEN_CURSOR_SHAPE_WAIT;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
shape = SCREEN_CURSOR_SHAPE_CROSS;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NWSE_RESIZE:
|
||||
case SDL_SYSTEM_CURSOR_NESW_RESIZE:
|
||||
case SDL_SYSTEM_CURSOR_EW_RESIZE:
|
||||
case SDL_SYSTEM_CURSOR_NS_RESIZE:
|
||||
case SDL_SYSTEM_CURSOR_MOVE:
|
||||
shape = SCREEN_CURSOR_SHAPE_MOVE;
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_POINTER:
|
||||
shape = SCREEN_CURSOR_SHAPE_HAND;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
static SDL_Cursor *genericCreateCursor(int shape)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
SDL_CursorData *impl;
|
||||
screen_session_t session;
|
||||
screen_context_t *context = getContext();
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(SDL_Cursor));
|
||||
if (cursor) {
|
||||
impl = SDL_calloc(1, sizeof(SDL_CursorData));;
|
||||
if (impl == NULL) {
|
||||
SDL_free(cursor);
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
impl->realized_shape = shape;
|
||||
|
||||
screen_create_session_type(&session, *context, SCREEN_EVENT_POINTER);
|
||||
screen_set_session_property_iv(session, SCREEN_PROPERTY_CURSOR, &shape);
|
||||
|
||||
impl->session = session;
|
||||
impl->is_visible = true;
|
||||
cursor->internal = (void*)impl;
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor *createCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||
{
|
||||
return genericCreateCursor(SCREEN_CURSOR_SHAPE_ARROW);
|
||||
}
|
||||
|
||||
static SDL_Cursor *createSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
int shape = SDLToScreenCursorShape(id);
|
||||
if (shape < 0) {
|
||||
SDL_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return genericCreateCursor(shape);
|
||||
}
|
||||
|
||||
static bool showCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
SDL_CursorData *impl;
|
||||
screen_session_t session;
|
||||
int shape;
|
||||
|
||||
// SDL does not provide information about previous visibility to its
|
||||
// drivers. We need to track that ourselves.
|
||||
if (cursor) {
|
||||
impl = (SDL_CursorData*)cursor->internal;
|
||||
SDL_assert(impl != NULL);
|
||||
if (impl->is_visible) {
|
||||
return true;
|
||||
}
|
||||
session = impl->session;
|
||||
shape = impl->realized_shape;
|
||||
impl->is_visible = true;
|
||||
} else {
|
||||
cursor = SDL_GetCursor();
|
||||
if (cursor == NULL) {
|
||||
return false;
|
||||
}
|
||||
impl = (SDL_CursorData*)cursor->internal;
|
||||
SDL_assert(impl != NULL);
|
||||
if (!impl->is_visible) {
|
||||
return 0;
|
||||
}
|
||||
session = impl->session;
|
||||
shape = SCREEN_CURSOR_SHAPE_NONE;
|
||||
impl->is_visible = false;
|
||||
}
|
||||
|
||||
if (screen_set_session_property_iv(session, SCREEN_PROPERTY_CURSOR, &shape) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void freeCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
SDL_CursorData *impl = (SDL_CursorData*)cursor->internal;
|
||||
if (impl != NULL) {
|
||||
screen_destroy_session(impl->session);
|
||||
SDL_free(impl);
|
||||
}
|
||||
SDL_free(cursor);
|
||||
}
|
||||
|
||||
static bool setRelativeMouseMode(bool enabled)
|
||||
{
|
||||
// We're tracking rel-position explicitly, but this is still needed so
|
||||
// SDL_SetRelativeMouseMode() & friends aren't a no-op.
|
||||
//
|
||||
// TODO: It may be possible to achieve this using SCREEN_PROPERTY_DISPLACEMENT instead.
|
||||
return true;
|
||||
}
|
||||
|
||||
void initMouse(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_MouseData *mouse_data;
|
||||
|
||||
mouse_data = (SDL_MouseData *)SDL_calloc(1, sizeof(SDL_MouseData));
|
||||
if (mouse_data == NULL) {
|
||||
return;
|
||||
}
|
||||
SDL_zerop(mouse_data);
|
||||
mouse->internal = mouse_data;
|
||||
|
||||
mouse->CreateCursor = createCursor;
|
||||
mouse->CreateSystemCursor = createSystemCursor;
|
||||
mouse->ShowCursor = showCursor;
|
||||
mouse->FreeCursor = freeCursor;
|
||||
|
||||
mouse->SetRelativeMouseMode = setRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(createCursor(NULL, 0, 0));
|
||||
}
|
||||
89
src/video/qnx/SDL_qnxpointer.c
Normal file
89
src/video/qnx/SDL_qnxpointer.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 2026 BlackBerry Limited
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_qnx.h"
|
||||
#include "SDL3/SDL_mouse.h"
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_video.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
||||
|
||||
static Uint8 screenToMouseButton(int x)
|
||||
{
|
||||
//Screen only supports 3 mouse buttons.
|
||||
switch(x){
|
||||
case SCREEN_LEFT_MOUSE_BUTTON: // 1 << 0
|
||||
return SDL_BUTTON_LEFT;
|
||||
case SCREEN_RIGHT_MOUSE_BUTTON: //1 << 1
|
||||
return SDL_BUTTON_RIGHT;
|
||||
case SCREEN_MIDDLE_MOUSE_BUTTON: //1 << 2
|
||||
return SDL_BUTTON_MIDDLE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handlePointerEvent(screen_event_t event)
|
||||
{
|
||||
int buttons = 0;
|
||||
int mouse_wheel = 0;
|
||||
int mouse_h_wheel = 0;
|
||||
int pos[2] = {0,0};
|
||||
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_Mouse *mouse;
|
||||
SDL_MouseData *mouse_data;
|
||||
SDL_Window *window;
|
||||
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttons);
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &mouse_wheel);
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_HORIZONTAL_WHEEL, &mouse_h_wheel);
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos);
|
||||
|
||||
mouse = SDL_GetMouse();
|
||||
|
||||
window = mouse->focus;
|
||||
mouse_data = mouse->internal;
|
||||
SDL_assert(mouse_data != NULL);
|
||||
|
||||
if (mouse->relative_mode) {
|
||||
// The mouse is hidden. We don't have control over its actual position
|
||||
// with SCREEN_PROPERTY_POSITION, just the position of the icon.
|
||||
SDL_SendMouseMotion(timestamp, window, SDL_DEFAULT_MOUSE_ID, true, pos[0] - mouse_data->x_prev, pos[1] - mouse_data->y_prev);
|
||||
} else {
|
||||
SDL_SendMouseMotion(timestamp, window, SDL_DEFAULT_MOUSE_ID, false, pos[0], pos[1]);
|
||||
}
|
||||
|
||||
mouse_data->x_prev = pos[0];
|
||||
mouse_data->y_prev = pos[1];
|
||||
|
||||
// Capture button presses
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Uint8 ret = screenToMouseButton(1 << i);
|
||||
SDL_SendMouseButton(timestamp, window, SDL_DEFAULT_MOUSE_ID, ret, (bool) ((buttons & (1 << i)) == (1 << i)));
|
||||
}
|
||||
|
||||
// Capture mouse wheel
|
||||
// TODO: Verify this. I can at least confirm that this behaves the same
|
||||
// way as x11.
|
||||
SDL_SendMouseWheel(timestamp, window, 0, (float) mouse_wheel, (float) mouse_h_wheel, SDL_MOUSEWHEEL_NORMAL);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user