mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-20 15:51:07 +01: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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -18,25 +18,54 @@
|
||||
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_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>
|
||||
|
||||
static screen_context_t context;
|
||||
static screen_event_t event;
|
||||
static bool video_initialized = false;
|
||||
|
||||
screen_context_t * getContext()
|
||||
{
|
||||
return &context;
|
||||
}
|
||||
|
||||
screen_event_t * getEvent()
|
||||
{
|
||||
return &event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the QNX video plugin.
|
||||
* Creates the Screen context and event handles used for all window operations
|
||||
* by the plugin.
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
static bool videoInit(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoDisplay display;
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayData *display_data;
|
||||
SDL_DisplayMode display_mode;
|
||||
SDL_DisplayModeData *display_mode_data;
|
||||
|
||||
int size[2];
|
||||
int index;
|
||||
int display_count;
|
||||
int active;
|
||||
|
||||
screen_display_t *screen_display;
|
||||
|
||||
if (video_initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (screen_create_context(&context, 0) < 0) {
|
||||
return false;
|
||||
@@ -46,21 +75,101 @@ static bool videoInit(SDL_VideoDevice *_this)
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_zero(display);
|
||||
|
||||
if (SDL_AddVideoDisplay(&display, false) == 0) {
|
||||
/* start with no displays and increment as attached displays are found */
|
||||
if (screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &display_count) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
screen_display = SDL_calloc(display_count, sizeof(screen_display_t));
|
||||
if (screen_display == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)screen_display) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* create SDL displays based on display info from the screen API */
|
||||
for (index = 0; index < display_count; index++) {
|
||||
active = 0;
|
||||
if (screen_get_display_property_iv(screen_display[index], SCREEN_PROPERTY_ATTACHED, &active) < 0) {
|
||||
SDL_free(screen_display);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (active) {
|
||||
display_data = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData));
|
||||
if (display_data == NULL) {
|
||||
SDL_free(screen_display);
|
||||
return false;
|
||||
}
|
||||
SDL_zerop(display_data);
|
||||
|
||||
if (screen_get_display_property_iv(screen_display[index], SCREEN_PROPERTY_SIZE, size) < 0) {
|
||||
SDL_free(screen_display);
|
||||
SDL_free(display_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
display_mode_data = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||
if (display_mode_data == NULL) {
|
||||
SDL_free(screen_display);
|
||||
SDL_free(display_data);
|
||||
return false;
|
||||
}
|
||||
SDL_zerop(display_mode_data);
|
||||
|
||||
SDL_zero(display);
|
||||
SDL_zero(display_mode);
|
||||
|
||||
display_data->screen_display = screen_display[index];
|
||||
display.internal = (void *)display_data;
|
||||
|
||||
display_mode.w = size[0];
|
||||
display_mode.h = size[1];
|
||||
display_mode.refresh_rate = 60;
|
||||
display_mode.pixel_density = 1.0;
|
||||
display_mode.internal = display_mode_data;
|
||||
// This is assigned later when the window is created. For now, use a
|
||||
// safe guess.
|
||||
display_mode.format = SDL_PIXELFORMAT_RGBX8888;
|
||||
display_mode_data->screen_format = SCREEN_FORMAT_RGBX8888;
|
||||
// Be able to revert to the default display mode despite not having
|
||||
// the actual object to refer to.
|
||||
display_mode_data->screen_display_mode.index = SCREEN_DISPLAY_MODE_PREFERRED_INDEX;
|
||||
|
||||
// Added to current_mode when the display is added.
|
||||
display.desktop_mode = display_mode;
|
||||
|
||||
if (!SDL_AddVideoDisplay(&display, false)) {
|
||||
SDL_free(screen_display);
|
||||
SDL_free(display_mode_data);
|
||||
SDL_free(display_data);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initMouse(_this);
|
||||
|
||||
// Assume we have a mouse and keyboard
|
||||
SDL_AddKeyboard(SDL_DEFAULT_KEYBOARD_ID, NULL);
|
||||
SDL_AddMouse(SDL_DEFAULT_MOUSE_ID, NULL);
|
||||
|
||||
video_initialized = true;
|
||||
|
||||
SDL_free(screen_display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void videoQuit(SDL_VideoDevice *_this)
|
||||
{
|
||||
if (video_initialized) {
|
||||
screen_destroy_event(event);
|
||||
screen_destroy_context(context);
|
||||
video_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,20 +177,27 @@ static void videoQuit(SDL_VideoDevice *_this)
|
||||
* window.
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param window SDL window to initialize
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
static bool createWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
static bool createWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
|
||||
{
|
||||
window_impl_t *impl;
|
||||
SDL_WindowData *impl;
|
||||
SDL_VideoDisplay *display = NULL;
|
||||
SDL_DisplayData *display_data = NULL;
|
||||
SDL_DisplayModeData *display_mode_data = NULL;
|
||||
|
||||
int size[2];
|
||||
int position[2];
|
||||
int numbufs;
|
||||
int format;
|
||||
int usage;
|
||||
int has_focus_i;
|
||||
|
||||
impl = SDL_calloc(1, sizeof(*impl));
|
||||
if (!impl) {
|
||||
return false;
|
||||
}
|
||||
window->internal = impl;
|
||||
|
||||
// Create a native window.
|
||||
if (screen_create_window(&impl->window, context) < 0) {
|
||||
@@ -91,6 +207,8 @@ static bool createWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
// Set the native window's size to match the SDL window.
|
||||
size[0] = window->w;
|
||||
size[1] = window->h;
|
||||
position[0] = window->x;
|
||||
position[1] = window->y;
|
||||
|
||||
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE,
|
||||
size) < 0) {
|
||||
@@ -102,23 +220,46 @@ static bool createWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_POSITION,
|
||||
position) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
display = SDL_GetVideoDisplayForWindow(window);
|
||||
SDL_assert(display != NULL);
|
||||
SDL_assert(display->desktop_mode.internal != NULL);
|
||||
display_mode_data = display->desktop_mode.internal;
|
||||
|
||||
if (screen_get_window_property_iv(impl->window, SCREEN_PROPERTY_FORMAT,
|
||||
&format) < 0) {
|
||||
format = display_mode_data->screen_format;
|
||||
}
|
||||
|
||||
// Create window buffer(s).
|
||||
if (window->flags & SDL_WINDOW_OPENGL) {
|
||||
if (glGetConfig(&impl->conf, &format) < 0) {
|
||||
if (!glInitConfig(impl, &format)) {
|
||||
goto fail;
|
||||
}
|
||||
numbufs = 2;
|
||||
|
||||
usage = SCREEN_USAGE_OPENGL_ES2;
|
||||
usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_OPENGL_ES3;
|
||||
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_USAGE,
|
||||
&usage) < 0) {
|
||||
return false;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
format = SCREEN_FORMAT_RGBX8888;
|
||||
numbufs = 1;
|
||||
}
|
||||
|
||||
// We now know what the pixel format is, so we need to provide it to the
|
||||
// right SDL APIs.
|
||||
display->desktop_mode.format = screenToPixelFormat(format);
|
||||
display_mode_data->screen_format = format;
|
||||
|
||||
display_data = display->internal;
|
||||
// Initialized in videoInit()
|
||||
SDL_assert(display_data != NULL);
|
||||
|
||||
// Set pixel format.
|
||||
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_FORMAT,
|
||||
&format) < 0) {
|
||||
@@ -126,19 +267,32 @@ static bool createWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
|
||||
// Create buffer(s).
|
||||
if (screen_create_window_buffers(impl->window, numbufs) < 0) {
|
||||
if (screen_create_window_buffers(impl->window, numbufs>0?numbufs:1) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
window->internal = impl;
|
||||
// Get initial focus state. Fallback to true.
|
||||
if(screen_get_window_property_iv(impl->window, SCREEN_PROPERTY_FOCUS, &has_focus_i) < 0){
|
||||
impl->has_focus = true;
|
||||
} else {
|
||||
impl->has_focus = (bool)has_focus_i;
|
||||
}
|
||||
|
||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_QNX_WINDOW_POINTER, impl->window);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if (impl->window) {
|
||||
screen_destroy_window(impl->window);
|
||||
}
|
||||
if (display_data) {
|
||||
SDL_free(display_data);
|
||||
display->internal = NULL;
|
||||
}
|
||||
|
||||
SDL_free(impl);
|
||||
window->internal = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -147,35 +301,43 @@ fail:
|
||||
* that the buffer is actually created in createWindow().
|
||||
* @param SDL_VideoDevice *_this
|
||||
* @param window SDL window to get the buffer for
|
||||
* @param[out] pixles Holds a pointer to the window's buffer
|
||||
* @param[out] pixels Holds a pointer to the window's buffer
|
||||
* @param[out] format Holds the pixel format for the buffer
|
||||
* @param[out] pitch Holds the number of bytes per line
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
static bool createWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, SDL_PixelFormat * format,
|
||||
void ** pixels, int *pitch)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
screen_buffer_t buffer;
|
||||
int buffer_count;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
screen_buffer_t *buffer;
|
||||
SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
|
||||
|
||||
if (screen_get_window_property_iv(impl->window, SCREEN_PROPERTY_BUFFER_COUNT,
|
||||
&buffer_count) < 0) {
|
||||
return false;
|
||||
}
|
||||
buffer = SDL_calloc(buffer_count, sizeof(screen_buffer_t));
|
||||
|
||||
// Get a pointer to the buffer's memory.
|
||||
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
|
||||
(void **)&buffer) < 0) {
|
||||
(void **)buffer) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER,
|
||||
if (screen_get_buffer_property_pv(*buffer, SCREEN_PROPERTY_POINTER,
|
||||
pixels) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set format and pitch.
|
||||
if (screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE,
|
||||
if (screen_get_buffer_property_iv(*buffer, SCREEN_PROPERTY_STRIDE,
|
||||
pitch) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*format = SDL_PIXELFORMAT_XRGB8888;
|
||||
*format = display->desktop_mode.format;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,31 +347,150 @@ static bool createWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window,
|
||||
* @param window The window to update
|
||||
* @param rects An array of reectangular areas to update
|
||||
* @param numrects Rect array length
|
||||
* @return 0 if successful, -1 on error
|
||||
* @return true if successful, false on error
|
||||
*/
|
||||
static bool updateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects,
|
||||
int numrects)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
screen_buffer_t buffer;
|
||||
int buffer_count, *rects_int;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
screen_buffer_t *buffer;
|
||||
|
||||
if (screen_get_window_property_iv(impl->window, SCREEN_PROPERTY_BUFFER_COUNT,
|
||||
&buffer_count) < 0) {
|
||||
return false;
|
||||
}
|
||||
buffer = SDL_calloc(buffer_count, sizeof(screen_buffer_t));
|
||||
|
||||
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
|
||||
(void **)&buffer) < 0) {
|
||||
(void **)buffer) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
screen_post_window(impl->window, buffer, numrects, (int *)rects, 0);
|
||||
screen_flush_context(context, 0);
|
||||
if(numrects>0){
|
||||
rects_int = SDL_calloc(4*numrects, sizeof(int));
|
||||
|
||||
for(int i = 0; i < numrects; i++){
|
||||
rects_int[4*i] = rects[i].x;
|
||||
rects_int[4*i+1] = rects[i].y;
|
||||
rects_int[4*i+2] = rects[i].w;
|
||||
rects_int[4*i+3] = rects[i].h;
|
||||
}
|
||||
|
||||
if(screen_post_window(impl->window, buffer[0], numrects, rects_int, 0)) {
|
||||
return false;
|
||||
}
|
||||
if(screen_flush_context(context, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_FullscreenResult setWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen)
|
||||
{
|
||||
SDL_WindowData *window_data = window->internal;
|
||||
SDL_DisplayData *display_data = display->internal;
|
||||
int size[2] = { 0, 0 };
|
||||
int position[2] = { 0, 0 };
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_FULLSCREEN) && !fullscreen) {
|
||||
return SDL_FULLSCREEN_SUCCEEDED;
|
||||
}
|
||||
|
||||
if (fullscreen) {
|
||||
SDL_Rect bounds;
|
||||
|
||||
if (!getDisplayBounds(_this, display, &bounds)) {
|
||||
return SDL_FULLSCREEN_FAILED;
|
||||
}
|
||||
position[0] = bounds.x;
|
||||
position[1] = bounds.y;
|
||||
size[0] = bounds.w;
|
||||
size[1] = bounds.h;
|
||||
} else {
|
||||
position[0] = window->x;
|
||||
position[1] = window->y;
|
||||
size[0] = window->w;
|
||||
size[1] = window->h;
|
||||
}
|
||||
|
||||
if (screen_set_window_property_iv(window_data->window, SCREEN_PROPERTY_SIZE,
|
||||
size) < 0) {
|
||||
return SDL_FULLSCREEN_FAILED;
|
||||
}
|
||||
|
||||
if (screen_set_window_property_iv(window_data->window, SCREEN_PROPERTY_SOURCE_SIZE,
|
||||
size) < 0) {
|
||||
return SDL_FULLSCREEN_FAILED;
|
||||
}
|
||||
|
||||
if (screen_set_window_property_iv(window_data->window, SCREEN_PROPERTY_POSITION,
|
||||
position) < 0) {
|
||||
return SDL_FULLSCREEN_FAILED;
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(window, fullscreen ? SDL_EVENT_WINDOW_ENTER_FULLSCREEN : SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0);
|
||||
|
||||
return SDL_FULLSCREEN_SUCCEEDED;
|
||||
}
|
||||
|
||||
static SDL_DisplayID getDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
// We need this, otherwise SDL will fallback to the primary display, meaning
|
||||
// any data we store about the display will be inconveniently overwritten.
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
SDL_DisplayData *display_data;
|
||||
|
||||
screen_display_t screen_display;
|
||||
|
||||
if (impl == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_DISPLAY,
|
||||
(void **)&screen_display) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _this->num_displays; i++) {
|
||||
display_data = _this->displays[i]->internal;
|
||||
if (display_data && (display_data->screen_display == screen_display)) {
|
||||
return _this->displays[i]->id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the main event loop.
|
||||
* @param SDL_VideoDevice *_this
|
||||
*/
|
||||
static void pumpEvents(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_WindowData *impl;
|
||||
int type;
|
||||
int has_focus_i;
|
||||
bool has_focus;
|
||||
|
||||
// Let apps know the state of focus.
|
||||
for (window = _this->windows; window; window = window->next) {
|
||||
impl = (SDL_WindowData *)window->internal;
|
||||
if (screen_get_window_property_iv(impl->window, SCREEN_PROPERTY_FOCUS, &has_focus_i) < 0){
|
||||
continue;
|
||||
}
|
||||
has_focus = (bool)has_focus_i;
|
||||
|
||||
if (impl->has_focus != has_focus) {
|
||||
SDL_SendWindowEvent(window, (has_focus ? SDL_EVENT_WINDOW_FOCUS_GAINED : SDL_EVENT_WINDOW_FOCUS_LOST), 0, 0);
|
||||
SDL_SendWindowEvent(window, (has_focus ? SDL_EVENT_WINDOW_MOUSE_ENTER : SDL_EVENT_WINDOW_MOUSE_LEAVE), 0, 0);
|
||||
// Update the SDL mouse to track the window it's focused on.
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (screen_get_event(context, event, 0) < 0) {
|
||||
@@ -230,6 +511,10 @@ static void pumpEvents(SDL_VideoDevice *_this)
|
||||
handleKeyboardEvent(event);
|
||||
break;
|
||||
|
||||
case SCREEN_EVENT_POINTER:
|
||||
handlePointerEvent(event);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -243,14 +528,25 @@ static void pumpEvents(SDL_VideoDevice *_this)
|
||||
*/
|
||||
static void setWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
int size[2];
|
||||
|
||||
size[0] = window->pending.w;
|
||||
size[1] = window->pending.h;
|
||||
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size);
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, size);
|
||||
if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) {
|
||||
if (screen_destroy_window_buffers(impl->window) < 0) {
|
||||
return;
|
||||
}
|
||||
impl->resize = 1;
|
||||
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size);
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE, size);
|
||||
|
||||
screen_create_window_buffers(impl->window, (window->flags & SDL_WINDOW_OPENGL) ? 2 : 1);
|
||||
} else {
|
||||
window->last_size_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,7 +556,7 @@ static void setWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
*/
|
||||
static void showWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
const int visible = 1;
|
||||
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
|
||||
@@ -274,7 +570,7 @@ static void showWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
*/
|
||||
static void hideWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
const int visible = 0;
|
||||
|
||||
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
|
||||
@@ -288,7 +584,7 @@ static void hideWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
*/
|
||||
static void destroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
window_impl_t *impl = (window_impl_t *)window->internal;
|
||||
SDL_WindowData *impl = (SDL_WindowData *)window->internal;
|
||||
|
||||
if (impl) {
|
||||
screen_destroy_window(impl->window);
|
||||
@@ -325,8 +621,15 @@ static SDL_VideoDevice *createDevice(void)
|
||||
device->CreateWindowFramebuffer = createWindowFramebuffer;
|
||||
device->UpdateWindowFramebuffer = updateWindowFramebuffer;
|
||||
device->SetWindowSize = setWindowSize;
|
||||
device->SetWindowFullscreen = setWindowFullscreen;
|
||||
device->ShowWindow = showWindow;
|
||||
device->HideWindow = hideWindow;
|
||||
device->GetDisplayForWindow = getDisplayForWindow;
|
||||
device->GetDisplayBounds = getDisplayBounds;
|
||||
device->GetDisplayModes = getDisplayModes;
|
||||
#if 0
|
||||
device->SetDisplayMode = setDisplayMode;
|
||||
#endif
|
||||
device->PumpEvents = pumpEvents;
|
||||
device->DestroyWindow = destroyWindow;
|
||||
|
||||
@@ -340,6 +643,7 @@ static SDL_VideoDevice *createDevice(void)
|
||||
device->GL_UnloadLibrary = glUnloadLibrary;
|
||||
|
||||
device->free = deleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user