mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 08:04:40 +00:00
update sdl to release 2.0.22
This commit is contained in:
parent
3f796d2a06
commit
d4307ea413
135 changed files with 5746 additions and 1161 deletions
|
|
@ -412,6 +412,12 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (biBitCount >= 32) { /* we shift biClrUsed by this value later. */
|
||||
SDL_SetError("Unsupported or incorrect biBitCount field");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (biClrUsed == 0) {
|
||||
biClrUsed = 1 << biBitCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#endif
|
||||
#if SDL_VIDEO_DRIVER_ANDROID
|
||||
#include <android/native_window.h>
|
||||
#include "../core/android/SDL_android.h"
|
||||
#include "../video/android/SDL_androidvideo.h"
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_RPI
|
||||
|
|
@ -99,7 +98,7 @@
|
|||
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
|
||||
#endif /* SDL_VIDEO_DRIVER_RPI */
|
||||
|
||||
#if SDL_VIDEO_OPENGL
|
||||
#if SDL_VIDEO_OPENGL && !SDL_VIDEO_VITA_PVR_OGL
|
||||
#include "SDL_opengl.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -530,7 +529,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
|
|||
}
|
||||
#endif
|
||||
/* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
|
||||
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
|
||||
if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) && (_this->egl_data->eglGetDisplay != NULL)) {
|
||||
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
|
||||
}
|
||||
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
|
||||
|
|
@ -1062,7 +1061,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
|
|||
if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) {
|
||||
_this->gl_allow_no_surface = SDL_TRUE;
|
||||
}
|
||||
#if SDL_VIDEO_OPENGL
|
||||
#if SDL_VIDEO_OPENGL && !defined(SDL_VIDEO_DRIVER_VITA)
|
||||
} else {
|
||||
/* Desktop OpenGL supports it by default from version 3.0 on. */
|
||||
void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "SDL_blit.h"
|
||||
#include "SDL_pixels_c.h"
|
||||
#include "SDL_RLEaccel_c.h"
|
||||
#include "../SDL_list.h"
|
||||
|
||||
|
||||
/* Lookup tables to expand partial bytes to the full 0..255 range */
|
||||
|
|
@ -1024,12 +1025,6 @@ SDL_AllocBlitMap(void)
|
|||
}
|
||||
|
||||
|
||||
typedef struct SDL_ListNode
|
||||
{
|
||||
void *entry;
|
||||
struct SDL_ListNode *next;
|
||||
} SDL_ListNode;
|
||||
|
||||
void
|
||||
SDL_InvalidateAllBlitMap(SDL_Surface *surface)
|
||||
{
|
||||
|
|
@ -1045,40 +1040,6 @@ SDL_InvalidateAllBlitMap(SDL_Surface *surface)
|
|||
}
|
||||
}
|
||||
|
||||
static void SDL_ListAdd(SDL_ListNode **head, void *ent);
|
||||
static void SDL_ListRemove(SDL_ListNode **head, void *ent);
|
||||
|
||||
void
|
||||
SDL_ListAdd(SDL_ListNode **head, void *ent)
|
||||
{
|
||||
SDL_ListNode *node = SDL_malloc(sizeof (*node));
|
||||
|
||||
if (node == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return;
|
||||
}
|
||||
|
||||
node->entry = ent;
|
||||
node->next = *head;
|
||||
*head = node;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_ListRemove(SDL_ListNode **head, void *ent)
|
||||
{
|
||||
SDL_ListNode **ptr = head;
|
||||
|
||||
while (*ptr) {
|
||||
if ((*ptr)->entry == ent) {
|
||||
SDL_ListNode *tmp = *ptr;
|
||||
*ptr = (*ptr)->next;
|
||||
SDL_free(tmp);
|
||||
return;
|
||||
}
|
||||
ptr = &(*ptr)->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_InvalidateMap(SDL_BlitMap * map)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ struct SDL_VideoDevice
|
|||
Uint32 next_object_id;
|
||||
char *clipboard_text;
|
||||
SDL_bool setting_display_mode;
|
||||
SDL_bool disable_display_mode_switching;
|
||||
|
||||
/* * * */
|
||||
/* Data used by the GL drivers */
|
||||
|
|
|
|||
|
|
@ -61,12 +61,12 @@ static VideoBootStrap *bootstrap[] = {
|
|||
#if SDL_VIDEO_DRIVER_COCOA
|
||||
&COCOA_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
&Wayland_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
&X11_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
&Wayland_bootstrap,
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_VIVANTE
|
||||
&VIVANTE_bootstrap,
|
||||
#endif
|
||||
|
|
@ -261,6 +261,7 @@ SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window * window, Uint32 * fo
|
|||
SDL_TEXTUREACCESS_STREAMING,
|
||||
window->w, window->h);
|
||||
if (!data->texture) {
|
||||
/* codechecker_false_positive [Malloc] Static analyzer doesn't realize allocated `data` is saved to SDL_WINDOWTEXTUREDATA and not leaked here. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -424,7 +425,7 @@ SDL_VideoInit(const char *driver_name)
|
|||
i = index = 0;
|
||||
video = NULL;
|
||||
if (driver_name == NULL) {
|
||||
driver_name = SDL_getenv("SDL_VIDEODRIVER");
|
||||
driver_name = SDL_GetHint(SDL_HINT_VIDEODRIVER);
|
||||
}
|
||||
if (driver_name != NULL && *driver_name != 0) {
|
||||
const char *driver_attempt = driver_name;
|
||||
|
|
@ -1184,6 +1185,7 @@ SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
|
|||
} else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
|
||||
&fullscreen_mode,
|
||||
&fullscreen_mode)) {
|
||||
SDL_zerop(mode);
|
||||
return SDL_SetError("Couldn't find display mode match");
|
||||
}
|
||||
|
||||
|
|
@ -1337,14 +1339,17 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
|
|||
resized = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* only do the mode change if we want exclusive fullscreen */
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
|
||||
return -1;
|
||||
/* Don't try to change the display mode if the driver doesn't want it. */
|
||||
if (_this->disable_display_mode_switching == SDL_FALSE) {
|
||||
/* only do the mode change if we want exclusive fullscreen */
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3055,7 +3060,8 @@ ShouldMinimizeOnFocusLoss(SDL_Window * window)
|
|||
/* Real fullscreen windows should minimize on focus loss so the desktop video mode is restored */
|
||||
hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
|
||||
if (!hint || !*hint || SDL_strcasecmp(hint, "auto") == 0) {
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP ||
|
||||
_this->disable_display_mode_switching == SDL_TRUE) {
|
||||
return SDL_FALSE;
|
||||
} else {
|
||||
return SDL_TRUE;
|
||||
|
|
@ -3919,6 +3925,10 @@ SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
|
|||
{
|
||||
int retval;
|
||||
|
||||
if (!_this) {
|
||||
return SDL_UninitializedVideo();
|
||||
}
|
||||
|
||||
if (window == SDL_GL_GetCurrentWindow() &&
|
||||
ctx == SDL_GL_GetCurrentContext()) {
|
||||
/* We're already current. */
|
||||
|
|
@ -4262,12 +4272,12 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
|
|||
#if SDL_VIDEO_DRIVER_UIKIT
|
||||
#include "uikit/SDL_uikitmessagebox.h"
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
#include "wayland/SDL_waylandmessagebox.h"
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
#include "x11/SDL_x11messagebox.h"
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
#include "wayland/SDL_waylandmessagebox.h"
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_HAIKU
|
||||
#include "haiku/SDL_bmessagebox.h"
|
||||
#endif
|
||||
|
|
@ -4375,13 +4385,6 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
retval = 0;
|
||||
}
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
if (retval == -1 &&
|
||||
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) &&
|
||||
Wayland_ShowMessageBox(messageboxdata, buttonid) == 0) {
|
||||
retval = 0;
|
||||
}
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
if (retval == -1 &&
|
||||
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_X11) &&
|
||||
|
|
@ -4389,6 +4392,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
retval = 0;
|
||||
}
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_WAYLAND
|
||||
if (retval == -1 &&
|
||||
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) &&
|
||||
Wayland_ShowMessageBox(messageboxdata, buttonid) == 0) {
|
||||
retval = 0;
|
||||
}
|
||||
#endif
|
||||
#if SDL_VIDEO_DRIVER_HAIKU
|
||||
if (retval == -1 &&
|
||||
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_HAIKU) &&
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ Android_CreateDevice(int devindex)
|
|||
device->SetWindowTitle = Android_SetWindowTitle;
|
||||
device->SetWindowFullscreen = Android_SetWindowFullscreen;
|
||||
device->MinimizeWindow = Android_MinimizeWindow;
|
||||
device->SetWindowResizable = Android_SetWindowResizable;
|
||||
device->DestroyWindow = Android_DestroyWindow;
|
||||
device->GetWindowWMInfo = Android_GetWindowWMInfo;
|
||||
|
||||
|
|
|
|||
|
|
@ -167,6 +167,12 @@ Android_MinimizeWindow(_THIS, SDL_Window *window)
|
|||
Android_JNI_MinizeWindow();
|
||||
}
|
||||
|
||||
void Android_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
|
||||
{
|
||||
/* Set orientation */
|
||||
Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
|
||||
}
|
||||
|
||||
void
|
||||
Android_DestroyWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ extern int Android_CreateWindow(_THIS, SDL_Window *window);
|
|||
extern void Android_SetWindowTitle(_THIS, SDL_Window *window);
|
||||
extern void Android_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
|
||||
extern void Android_MinimizeWindow(_THIS, SDL_Window *window);
|
||||
extern void Android_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable);
|
||||
|
||||
extern void Android_DestroyWindow(_THIS, SDL_Window *window);
|
||||
extern SDL_bool Android_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "SDL_nullvideo.h"
|
||||
#include "SDL_nullevents_c.h"
|
||||
#include "SDL_nullframebuffer_c.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#define DUMMYVID_DRIVER_NAME "dummy"
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ static void DUMMY_VideoQuit(_THIS);
|
|||
static int
|
||||
DUMMY_Available(void)
|
||||
{
|
||||
const char *envr = SDL_getenv("SDL_VIDEODRIVER");
|
||||
const char *envr = SDL_GetHint(SDL_HINT_VIDEODRIVER);
|
||||
if ((envr) && (SDL_strcmp(envr, DUMMYVID_DRIVER_NAME) == 0)) {
|
||||
return (1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "SDL_emscriptenframebuffer.h"
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#include <emscripten/threading.h>
|
||||
|
||||
|
||||
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
|
||||
{
|
||||
|
|
@ -57,18 +59,9 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * form
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
|
||||
static void
|
||||
Emscripten_UpdateWindowFramebufferWorker(SDL_Surface* surface)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
surface = data->surface;
|
||||
if (!surface) {
|
||||
return SDL_SetError("Couldn't find framebuffer surface for window");
|
||||
}
|
||||
|
||||
/* Send the data to the display */
|
||||
|
||||
EM_ASM_INT({
|
||||
var w = $0;
|
||||
var h = $1;
|
||||
|
|
@ -156,6 +149,29 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
|
|||
SDL2.ctx.putImageData(SDL2.image, 0, 0);
|
||||
return 0;
|
||||
}, surface->w, surface->h, surface->pixels);
|
||||
}
|
||||
|
||||
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
surface = data->surface;
|
||||
if (!surface) {
|
||||
return SDL_SetError("Couldn't find framebuffer surface for window");
|
||||
}
|
||||
|
||||
/* Send the data to the display */
|
||||
|
||||
if (emscripten_is_main_runtime_thread()) {
|
||||
Emscripten_UpdateWindowFramebufferWorker(surface);
|
||||
} else {
|
||||
emscripten_sync_run_in_main_runtime_thread(
|
||||
EM_FUNC_SIG_VI,
|
||||
Emscripten_UpdateWindowFramebufferWorker,
|
||||
(uint32_t)surface
|
||||
);
|
||||
}
|
||||
|
||||
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
|
||||
/* give back control to browser for screen refresh */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/threading.h>
|
||||
|
||||
#include "SDL_emscriptenmouse.h"
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
|
|
@ -62,19 +63,10 @@ Emscripten_CreateDefaultCursor()
|
|||
return Emscripten_CreateCursorFromString("default", SDL_FALSE);
|
||||
}
|
||||
|
||||
static SDL_Cursor*
|
||||
Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
|
||||
static const char*
|
||||
Emscripten_GetCursorUrl(int w, int h, int hot_x, int hot_y, void* pixels)
|
||||
{
|
||||
const char *cursor_url = NULL;
|
||||
SDL_Surface *conv_surf;
|
||||
|
||||
conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
|
||||
|
||||
if (!conv_surf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor_url = (const char *)EM_ASM_INT({
|
||||
return (const char *)EM_ASM_INT({
|
||||
var w = $0;
|
||||
var h = $1;
|
||||
var hot_x = $2;
|
||||
|
|
@ -122,7 +114,40 @@ Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
|
|||
stringToUTF8(url, urlBuf, url.length + 1);
|
||||
|
||||
return urlBuf;
|
||||
}, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
|
||||
}, w, h, hot_x, hot_y, pixels);
|
||||
}
|
||||
|
||||
static SDL_Cursor*
|
||||
Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
|
||||
{
|
||||
const char *cursor_url = NULL;
|
||||
SDL_Surface *conv_surf;
|
||||
|
||||
conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
|
||||
|
||||
if (!conv_surf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (emscripten_is_main_runtime_thread()) {
|
||||
cursor_url = Emscripten_GetCursorUrl(
|
||||
surface->w,
|
||||
surface->h,
|
||||
hot_x,
|
||||
hot_y,
|
||||
conv_surf->pixels
|
||||
);
|
||||
} else {
|
||||
cursor_url = (const char *)emscripten_sync_run_in_main_runtime_thread(
|
||||
EM_FUNC_SIG_IIIIIII,
|
||||
Emscripten_GetCursorUrl,
|
||||
surface->w,
|
||||
surface->h,
|
||||
hot_x,
|
||||
hot_y,
|
||||
conv_surf->pixels
|
||||
);
|
||||
}
|
||||
|
||||
SDL_FreeSurface(conv_surf);
|
||||
|
||||
|
|
@ -206,16 +231,15 @@ Emscripten_ShowCursor(SDL_Cursor* cursor)
|
|||
curdata = (Emscripten_CursorData *) cursor->driverdata;
|
||||
|
||||
if(curdata->system_cursor) {
|
||||
EM_ASM_INT({
|
||||
MAIN_THREAD_EM_ASM({
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = UTF8ToString($0);
|
||||
}
|
||||
return 0;
|
||||
}, curdata->system_cursor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EM_ASM(
|
||||
MAIN_THREAD_EM_ASM(
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = 'none';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,10 +174,10 @@ Emscripten_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect *
|
|||
if (rect) {
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
rect->w = EM_ASM_INT_V({
|
||||
rect->w = MAIN_THREAD_EM_ASM_INT({
|
||||
return window.innerWidth;
|
||||
});
|
||||
rect->h = EM_ASM_INT_V({
|
||||
rect->h = MAIN_THREAD_EM_ASM_INT({
|
||||
return window.innerHeight;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *but
|
|||
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
static void
|
||||
UIKit_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
|
||||
{
|
||||
BOOL success = NO;
|
||||
|
||||
|
|
@ -199,12 +199,26 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
}
|
||||
|
||||
if (!success) {
|
||||
return SDL_SetError("Could not show message box.");
|
||||
*returnValue = SDL_SetError("Could not show message box.");
|
||||
} else {
|
||||
*returnValue = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
__block int returnValue = 0;
|
||||
|
||||
if ([NSThread isMainThread]) {
|
||||
UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue);
|
||||
} else {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{ UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue); });
|
||||
}
|
||||
return returnValue;
|
||||
}}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_UIKIT */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||
#define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
|
||||
|
||||
void *vita_gpu_alloc(SceKernelMemBlockType type, unsigned int size, SceUID *uid)
|
||||
void *vita_gpu_alloc(unsigned int type, unsigned int size, SceUID *uid)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@
|
|||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR
|
||||
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR && SDL_VIDEO_VITA_PVR_OGL
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <psp2/kernel/modulemgr.h>
|
||||
#include <gpu_es4/psp2_pvr_hint.h>
|
||||
#include <gl4esinit.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_log.h"
|
||||
|
|
@ -34,6 +35,16 @@
|
|||
|
||||
#define MAX_PATH 256 // vita limits are somehow wrong
|
||||
|
||||
/* Defaults */
|
||||
int FB_WIDTH = 960;
|
||||
int FB_HEIGHT = 544;
|
||||
|
||||
void getFBSize(int *width, int *height)
|
||||
{
|
||||
*width = FB_WIDTH;
|
||||
*height = FB_HEIGHT;
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GL_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
|
|
@ -53,6 +64,9 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
|
|||
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
|
||||
sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
|
||||
|
||||
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libGL.suprx");
|
||||
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
|
||||
|
||||
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
|
||||
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
|
||||
|
||||
|
|
@ -74,30 +88,45 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
|
|||
SDL_GLContext
|
||||
VITA_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
}
|
||||
char gl_version[3];
|
||||
SDL_GLContext context = NULL;
|
||||
int temp_major = _this->gl_config.major_version;
|
||||
int temp_minor = _this->gl_config.minor_version;
|
||||
int temp_profile = _this->gl_config.profile_mask;
|
||||
|
||||
int
|
||||
VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
if (window && context) {
|
||||
return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
|
||||
} else {
|
||||
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
|
||||
/* Set version to 2.0 and PROFILE to ES */
|
||||
_this->gl_config.major_version = 2;
|
||||
_this->gl_config.minor_version = 0;
|
||||
_this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
|
||||
context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
|
||||
if (context != NULL)
|
||||
{
|
||||
FB_WIDTH = window->w;
|
||||
FB_HEIGHT = window->h;
|
||||
set_getprocaddress((void *(*)(const char *))eglGetProcAddress);
|
||||
set_getmainfbsize(getFBSize);
|
||||
SDL_snprintf(gl_version, 3, "%d%d", temp_major, temp_minor);
|
||||
gl4es_setenv("LIBGL_NOTEXRECT", "1", 1); /* Currently broken in driver */
|
||||
gl4es_setenv("LIBGL_GL", gl_version, 1);
|
||||
initialize_gl4es();
|
||||
}
|
||||
|
||||
/* Restore gl_config */
|
||||
_this->gl_config.major_version = temp_major;
|
||||
_this->gl_config.minor_version = temp_minor;
|
||||
_this->gl_config.profile_mask = temp_profile;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
void *
|
||||
VITA_GL_GetProcAddress(_THIS, const char *proc)
|
||||
{
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
if (videodata->ime_active) {
|
||||
sceImeUpdate();
|
||||
}
|
||||
return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
return gl4es_GetProcAddress(proc);
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -19,17 +19,16 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_vitagl_c_h_
|
||||
#define SDL_vitagl_c_h_
|
||||
#ifndef SDL_vitagl_pvr_c_h_
|
||||
#define SDL_vitagl_pvr_c_h_
|
||||
|
||||
#include "SDL_vitavideo.h"
|
||||
|
||||
extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
|
||||
extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
|
||||
extern int VITA_GL_LoadLibrary(_THIS, const char *path);
|
||||
extern void *VITA_GL_GetProcAddress(_THIS, const char *proc);
|
||||
|
||||
|
||||
#endif /* SDL_vitagl_c_h_ */
|
||||
#endif /* SDL_vitagl_pvr_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "SDL_error.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_vitavideo.h"
|
||||
#include "SDL_vitagl_c.h"
|
||||
#include "SDL_vitagles_c.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SDL OpenGL/OpenGL ES functions */
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
} while (0)
|
||||
|
||||
void
|
||||
VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
|
||||
VITA_GLES_KeyboardCallback(ScePigletPreSwapData *data)
|
||||
{
|
||||
SceCommonDialogUpdateParam commonDialogParam;
|
||||
SDL_zero(commonDialogParam);
|
||||
|
|
@ -62,20 +62,20 @@ VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
|
|||
}
|
||||
|
||||
int
|
||||
VITA_GL_LoadLibrary(_THIS, const char *path)
|
||||
VITA_GLES_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
pibInit(PIB_SHACCCG | PIB_GET_PROC_ADDR_CORE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
VITA_GL_GetProcAddress(_THIS, const char *proc)
|
||||
VITA_GLES_GetProcAddress(_THIS, const char *proc)
|
||||
{
|
||||
return eglGetProcAddress(proc);
|
||||
}
|
||||
|
||||
void
|
||||
VITA_GL_UnloadLibrary(_THIS)
|
||||
VITA_GLES_UnloadLibrary(_THIS)
|
||||
{
|
||||
eglTerminate(_this->gl_data->display);
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ static EGLint width = 960;
|
|||
static EGLint height = 544;
|
||||
|
||||
SDL_GLContext
|
||||
VITA_GL_CreateContext(_THIS, SDL_Window * window)
|
||||
VITA_GLES_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
|
||||
SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
|
||||
|
|
@ -159,13 +159,13 @@ VITA_GL_CreateContext(_THIS, SDL_Window * window)
|
|||
_this->gl_data->surface = surface;
|
||||
|
||||
preSwapCallback = (PFNEGLPIGLETVITASETPRESWAPCALLBACKSCEPROC) eglGetProcAddress("eglPigletVitaSetPreSwapCallbackSCE");
|
||||
preSwapCallback(VITA_GL_KeyboardCallback);
|
||||
preSwapCallback(VITA_GLES_KeyboardCallback);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
if (!eglMakeCurrent(_this->gl_data->display, _this->gl_data->surface,
|
||||
_this->gl_data->surface, _this->gl_data->context))
|
||||
|
|
@ -176,7 +176,7 @@ VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
|||
}
|
||||
|
||||
int
|
||||
VITA_GL_SetSwapInterval(_THIS, int interval)
|
||||
VITA_GLES_SetSwapInterval(_THIS, int interval)
|
||||
{
|
||||
EGLBoolean status;
|
||||
status = eglSwapInterval(_this->gl_data->display, interval);
|
||||
|
|
@ -190,13 +190,13 @@ VITA_GL_SetSwapInterval(_THIS, int interval)
|
|||
}
|
||||
|
||||
int
|
||||
VITA_GL_GetSwapInterval(_THIS)
|
||||
VITA_GLES_GetSwapInterval(_THIS)
|
||||
{
|
||||
return _this->gl_data->swapinterval;
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||
VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
if (!eglSwapBuffers(_this->gl_data->display, _this->gl_data->surface)) {
|
||||
return SDL_SetError("eglSwapBuffers() failed");
|
||||
|
|
@ -205,7 +205,7 @@ VITA_GL_SwapWindow(_THIS, SDL_Window * window)
|
|||
}
|
||||
|
||||
void
|
||||
VITA_GL_DeleteContext(_THIS, SDL_GLContext context)
|
||||
VITA_GLES_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
|
||||
EGLBoolean status;
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_vitagl_c_h_
|
||||
#define SDL_vitagl_c_h_
|
||||
#ifndef SDL_vitagles_c_h_
|
||||
#define SDL_vitagles_c_h_
|
||||
|
||||
|
||||
#include <pib.h>
|
||||
|
|
@ -39,19 +39,19 @@ typedef struct SDL_GLDriverData {
|
|||
uint32_t swapinterval;
|
||||
}SDL_GLDriverData;
|
||||
|
||||
extern void * VITA_GL_GetProcAddress(_THIS, const char *proc);
|
||||
extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
|
||||
extern void VITA_GL_SwapBuffers(_THIS);
|
||||
extern void * VITA_GLES_GetProcAddress(_THIS, const char *proc);
|
||||
extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
|
||||
extern void VITA_GLES_SwapBuffers(_THIS);
|
||||
|
||||
extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
|
||||
extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
|
||||
|
||||
extern int VITA_GL_LoadLibrary(_THIS, const char *path);
|
||||
extern void VITA_GL_UnloadLibrary(_THIS);
|
||||
extern int VITA_GL_SetSwapInterval(_THIS, int interval);
|
||||
extern int VITA_GL_GetSwapInterval(_THIS);
|
||||
extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
|
||||
extern void VITA_GLES_UnloadLibrary(_THIS);
|
||||
extern int VITA_GLES_SetSwapInterval(_THIS, int interval);
|
||||
extern int VITA_GLES_GetSwapInterval(_THIS);
|
||||
|
||||
|
||||
#endif /* SDL_vitagl_c_h_ */
|
||||
#endif /* SDL_vitagles_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
103
Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr.c
Normal file
103
Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <psp2/kernel/modulemgr.h>
|
||||
#include <gpu_es4/psp2_pvr_hint.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_vitavideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "SDL_vitagles_pvr_c.h"
|
||||
|
||||
#define MAX_PATH 256 // vita limits are somehow wrong
|
||||
|
||||
int
|
||||
VITA_GLES_LoadLibrary(_THIS, const char *path)
|
||||
{
|
||||
PVRSRV_PSP2_APPHINT hint;
|
||||
char* override = SDL_getenv("VITA_MODULE_PATH");
|
||||
char* skip_init = SDL_getenv("VITA_PVR_SKIP_INIT");
|
||||
char* default_path = "app0:module";
|
||||
char target_path[MAX_PATH];
|
||||
|
||||
if (skip_init == NULL) // we don't care about actual value
|
||||
{
|
||||
if (override != NULL)
|
||||
{
|
||||
default_path = override;
|
||||
}
|
||||
|
||||
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
|
||||
sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
|
||||
|
||||
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
|
||||
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
|
||||
|
||||
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libIMGEGL.suprx");
|
||||
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
|
||||
|
||||
PVRSRVInitializeAppHint(&hint);
|
||||
|
||||
SDL_snprintf(hint.szGLES1, MAX_PATH, "%s/%s", default_path, "libGLESv1_CM.suprx");
|
||||
SDL_snprintf(hint.szGLES2, MAX_PATH, "%s/%s", default_path, "libGLESv2.suprx");
|
||||
SDL_snprintf(hint.szWindowSystem, MAX_PATH, "%s/%s", default_path, "libpvrPSP2_WSEGL.suprx");
|
||||
|
||||
PVRSRVCreateVirtualAppHint(&hint);
|
||||
}
|
||||
|
||||
return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0, 0);
|
||||
}
|
||||
|
||||
SDL_GLContext
|
||||
VITA_GLES_CreateContext(_THIS, SDL_Window * window)
|
||||
{
|
||||
return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
|
||||
{
|
||||
if (window && context) {
|
||||
return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
|
||||
} else {
|
||||
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
if (videodata->ime_active) {
|
||||
sceImeUpdate();
|
||||
}
|
||||
return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
|
||||
}
|
||||
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
35
Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr_c.h
Normal file
35
Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr_c.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef SDL_vitagles_pvr_c_h_
|
||||
#define SDL_vitagles_pvr_c_h_
|
||||
|
||||
#include "SDL_vitavideo.h"
|
||||
|
||||
extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
|
||||
extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
|
||||
extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
|
||||
|
||||
|
||||
#endif /* SDL_vitagles_pvr_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
@ -41,15 +41,17 @@
|
|||
#include "SDL_vitaframebuffer.h"
|
||||
|
||||
#if defined(SDL_VIDEO_VITA_PIB)
|
||||
#include "SDL_vitagl_c.h"
|
||||
#include "SDL_vitagles_c.h"
|
||||
#elif defined(SDL_VIDEO_VITA_PVR)
|
||||
#include "SDL_vitagles_pvr_c.h"
|
||||
#if defined(SDL_VIDEO_VITA_PVR_OGL)
|
||||
#include "SDL_vitagl_pvr_c.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#define VITA_GL_GetProcAddress SDL_EGL_GetProcAddress
|
||||
#define VITA_GL_UnloadLibrary SDL_EGL_UnloadLibrary
|
||||
#define VITA_GL_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
#define VITA_GL_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
#define VITA_GL_DeleteContext SDL_EGL_DeleteContext
|
||||
#endif
|
||||
#define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddress
|
||||
#define VITA_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
|
||||
#define VITA_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
#define VITA_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
#define VITA_GLES_DeleteContext SDL_EGL_DeleteContext
|
||||
#endif
|
||||
|
||||
SDL_Window *Vita_Window;
|
||||
|
|
@ -140,15 +142,26 @@ VITA_Create()
|
|||
*/
|
||||
|
||||
#if defined(SDL_VIDEO_VITA_PIB) || defined(SDL_VIDEO_VITA_PVR)
|
||||
#if defined(SDL_VIDEO_VITA_PVR_OGL)
|
||||
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
|
||||
device->GL_LoadLibrary = VITA_GL_LoadLibrary;
|
||||
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
|
||||
device->GL_UnloadLibrary = VITA_GL_UnloadLibrary;
|
||||
device->GL_CreateContext = VITA_GL_CreateContext;
|
||||
device->GL_MakeCurrent = VITA_GL_MakeCurrent;
|
||||
device->GL_SetSwapInterval = VITA_GL_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = VITA_GL_GetSwapInterval;
|
||||
device->GL_SwapWindow = VITA_GL_SwapWindow;
|
||||
device->GL_DeleteContext = VITA_GL_DeleteContext;
|
||||
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
|
||||
} else {
|
||||
#endif
|
||||
device->GL_LoadLibrary = VITA_GLES_LoadLibrary;
|
||||
device->GL_CreateContext = VITA_GLES_CreateContext;
|
||||
device->GL_GetProcAddress = VITA_GLES_GetProcAddress;
|
||||
#if defined(SDL_VIDEO_VITA_PVR_OGL)
|
||||
}
|
||||
#endif
|
||||
|
||||
device->GL_UnloadLibrary = VITA_GLES_UnloadLibrary;
|
||||
device->GL_MakeCurrent = VITA_GLES_MakeCurrent;
|
||||
device->GL_SetSwapInterval = VITA_GLES_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = VITA_GLES_GetSwapInterval;
|
||||
device->GL_SwapWindow = VITA_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = VITA_GLES_DeleteContext;
|
||||
#endif
|
||||
|
||||
device->HasScreenKeyboardSupport = VITA_HasScreenKeyboardSupport;
|
||||
|
|
@ -245,6 +258,9 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *wdata;
|
||||
#if defined(SDL_VIDEO_VITA_PVR)
|
||||
Psp2NativeWindow win;
|
||||
int temp_major = 2;
|
||||
int temp_minor = 1;
|
||||
int temp_profile = 0;
|
||||
#endif
|
||||
|
||||
/* Allocate window internal data */
|
||||
|
|
@ -282,11 +298,26 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
|
|||
win.windowSize = PSP2_WINDOW_960X544;
|
||||
}
|
||||
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
|
||||
wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
|
||||
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
|
||||
/* Set version to 2.1 and PROFILE to ES */
|
||||
temp_major = _this->gl_config.major_version;
|
||||
temp_minor = _this->gl_config.minor_version;
|
||||
temp_profile = _this->gl_config.profile_mask;
|
||||
|
||||
_this->gl_config.major_version = 2;
|
||||
_this->gl_config.minor_version = 1;
|
||||
_this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
}
|
||||
wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
|
||||
if (wdata->egl_surface == EGL_NO_SURFACE) {
|
||||
return SDL_SetError("Could not create GLES window surface");
|
||||
}
|
||||
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
|
||||
/* Revert */
|
||||
_this->gl_config.major_version = temp_major;
|
||||
_this->gl_config.minor_version = temp_minor;
|
||||
_this->gl_config.profile_mask = temp_profile;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -90,16 +90,23 @@ SDL_bool VITA_GetWindowWMInfo(_THIS, SDL_Window * window,
|
|||
struct SDL_SysWMinfo *info);
|
||||
|
||||
#if SDL_VIDEO_DRIVER_VITA
|
||||
#if defined(SDL_VIDEO_VITA_PVR_OGL)
|
||||
/* OpenGL functions */
|
||||
int VITA_GL_LoadLibrary(_THIS, const char *path);
|
||||
void *VITA_GL_GetProcAddress(_THIS, const char *proc);
|
||||
void VITA_GL_UnloadLibrary(_THIS);
|
||||
SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
|
||||
int VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
|
||||
int VITA_GL_SetSwapInterval(_THIS, int interval);
|
||||
int VITA_GL_GetSwapInterval(_THIS);
|
||||
int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
|
||||
void VITA_GL_DeleteContext(_THIS, SDL_GLContext context);
|
||||
void *VITA_GL_GetProcAddress(_THIS, const char *proc);
|
||||
#endif
|
||||
|
||||
/* OpenGLES functions */
|
||||
int VITA_GLES_LoadLibrary(_THIS, const char *path);
|
||||
void *VITA_GLES_GetProcAddress(_THIS, const char *proc);
|
||||
void VITA_GLES_UnloadLibrary(_THIS);
|
||||
SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
|
||||
int VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
|
||||
int VITA_GLES_SetSwapInterval(_THIS, int interval);
|
||||
int VITA_GLES_GetSwapInterval(_THIS);
|
||||
int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
|
||||
void VITA_GLES_DeleteContext(_THIS, SDL_GLContext context);
|
||||
#endif
|
||||
|
||||
/* VITA on screen keyboard */
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@ enum libdecor_window_state;
|
|||
#include "xkbcommon/xkbcommon.h"
|
||||
#include "xkbcommon/xkbcommon-compose.h"
|
||||
|
||||
/* Must be included before our #defines, see Bugzilla #4957 */
|
||||
#include "wayland-client-core.h"
|
||||
|
||||
#define SDL_WAYLAND_CHECK_VERSION(x, y, z) \
|
||||
(WAYLAND_VERSION_MAJOR > x || \
|
||||
(WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR > y) || \
|
||||
(WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR == y && WAYLAND_VERSION_MICRO >= z))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
|
@ -71,9 +79,6 @@ void SDL_WAYLAND_UnloadSymbols(void);
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Must be included before our #defines, see Bugzilla #4957 */
|
||||
#include "wayland-client-core.h"
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
|
||||
|
||||
#if defined(_WAYLAND_CLIENT_H) || defined(WAYLAND_CLIENT_H)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "xdg-shell-client-protocol.h"
|
||||
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "text-input-unstable-v3-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
|
@ -83,6 +84,7 @@ static const struct {
|
|||
{ XKB_KEY_Super_R, SDLK_RGUI },
|
||||
{ XKB_KEY_Hyper_L, SDLK_LGUI },
|
||||
{ XKB_KEY_Hyper_R, SDLK_RGUI },
|
||||
{ XKB_KEY_BackSpace, SDLK_BACKSPACE },
|
||||
};
|
||||
|
||||
struct SDL_WaylandTouchPoint {
|
||||
|
|
@ -387,8 +389,10 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
|
|||
input->sx_w = sx_w;
|
||||
input->sy_w = sy_w;
|
||||
if (input->pointer_focus) {
|
||||
const int sx = wl_fixed_to_int(sx_w);
|
||||
const int sy = wl_fixed_to_int(sy_w);
|
||||
const float sx_f = (float)wl_fixed_to_double(sx_w);
|
||||
const float sy_f = (float)wl_fixed_to_double(sy_w);
|
||||
const int sx = (int)SDL_floorf(sx_f * window->pointer_scale_x);
|
||||
const int sy = (int)SDL_floorf(sy_f * window->pointer_scale_y);
|
||||
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
|
||||
}
|
||||
}
|
||||
|
|
@ -472,6 +476,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
|
|||
const uint32_t *directions_libdecor = directions;
|
||||
#endif
|
||||
|
||||
/* Hit tests shouldn't apply to xdg_popups, right? */
|
||||
SDL_assert(!WINDOW_IS_XDG_POPUP(window));
|
||||
|
||||
switch (rc) {
|
||||
case SDL_HITTEST_DRAGGABLE:
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
|
|
@ -715,8 +722,8 @@ touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
|
|||
int id, wl_fixed_t fx, wl_fixed_t fy)
|
||||
{
|
||||
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
|
||||
const double dblx = wl_fixed_to_double(fx);
|
||||
const double dbly = wl_fixed_to_double(fy);
|
||||
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
|
||||
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
|
||||
const float x = dblx / window_data->sdlwindow->w;
|
||||
const float y = dbly / window_data->sdlwindow->h;
|
||||
|
||||
|
|
@ -748,8 +755,8 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
|
|||
int id, wl_fixed_t fx, wl_fixed_t fy)
|
||||
{
|
||||
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
|
||||
const double dblx = wl_fixed_to_double(fx);
|
||||
const double dbly = wl_fixed_to_double(fy);
|
||||
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
|
||||
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
|
||||
const float x = dblx / window_data->sdlwindow->w;
|
||||
const float y = dbly / window_data->sdlwindow->h;
|
||||
|
||||
|
|
@ -815,6 +822,16 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
|||
return;
|
||||
}
|
||||
|
||||
#define GET_MOD_INDEX(mod) \
|
||||
WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_##mod)
|
||||
input->xkb.idx_shift = 1 << GET_MOD_INDEX(SHIFT);
|
||||
input->xkb.idx_ctrl = 1 << GET_MOD_INDEX(CTRL);
|
||||
input->xkb.idx_alt = 1 << GET_MOD_INDEX(ALT);
|
||||
input->xkb.idx_gui = 1 << GET_MOD_INDEX(LOGO);
|
||||
input->xkb.idx_num = 1 << GET_MOD_INDEX(NUM);
|
||||
input->xkb.idx_caps = 1 << GET_MOD_INDEX(CAPS);
|
||||
#undef GET_MOD_INDEX
|
||||
|
||||
input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
|
||||
if (!input->xkb.state) {
|
||||
fprintf(stderr, "failed to create XKB state\n");
|
||||
|
|
@ -829,10 +846,14 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
|||
*/
|
||||
|
||||
/* Look up the preferred locale, falling back to "C" as default */
|
||||
if (!(locale = SDL_getenv("LC_ALL")))
|
||||
if (!(locale = SDL_getenv("LC_CTYPE")))
|
||||
if (!(locale = SDL_getenv("LANG")))
|
||||
if (!(locale = SDL_getenv("LC_ALL"))) {
|
||||
if (!(locale = SDL_getenv("LC_CTYPE"))) {
|
||||
if (!(locale = SDL_getenv("LANG"))) {
|
||||
locale = "C";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up XKB compose table */
|
||||
input->xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(input->display->xkb_context,
|
||||
locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
|
|
@ -903,7 +924,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, SDL_bool *handled_by_ime)
|
||||
keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime)
|
||||
{
|
||||
SDL_WindowData *window = input->keyboard_focus;
|
||||
const xkb_keysym_t *syms;
|
||||
|
|
@ -920,12 +941,16 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
|
|||
sym = syms[0];
|
||||
|
||||
#ifdef SDL_USE_IME
|
||||
if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
|
||||
if (SDL_IME_ProcessKeyEvent(sym, key + 8, state)) {
|
||||
*handled_by_ime = SDL_TRUE;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state == SDL_RELEASED) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (input->xkb.compose_state && WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
|
||||
switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
|
||||
case XKB_COMPOSE_COMPOSING:
|
||||
|
|
@ -959,7 +984,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|||
SDL_bool handled_by_ime = SDL_FALSE;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
has_text = keyboard_input_get_text(text, input, key, &handled_by_ime);
|
||||
has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
|
||||
} else {
|
||||
if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
|
||||
// Send any due key repeat events before stopping the repeat and generating the key up event
|
||||
|
|
@ -969,6 +994,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|||
keyboard_repeat_handle(&input->keyboard_repeat, time - input->keyboard_repeat.wl_press_time);
|
||||
keyboard_repeat_clear(&input->keyboard_repeat);
|
||||
}
|
||||
keyboard_input_get_text(text, input, key, SDL_RELEASED, &handled_by_ime);
|
||||
}
|
||||
|
||||
if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) {
|
||||
|
|
@ -1054,10 +1080,24 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
|||
{
|
||||
struct SDL_WaylandInput *input = data;
|
||||
Wayland_Keymap keymap;
|
||||
uint32_t modstate = (mods_depressed | mods_latched | mods_locked);
|
||||
|
||||
WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
|
||||
mods_locked, 0, 0, group);
|
||||
|
||||
SDL_ToggleModState(KMOD_SHIFT, modstate & input->xkb.idx_shift);
|
||||
SDL_ToggleModState(KMOD_CTRL, modstate & input->xkb.idx_ctrl);
|
||||
SDL_ToggleModState(KMOD_ALT, modstate & input->xkb.idx_alt);
|
||||
SDL_ToggleModState(KMOD_GUI, modstate & input->xkb.idx_gui);
|
||||
SDL_ToggleModState(KMOD_NUM, modstate & input->xkb.idx_num);
|
||||
SDL_ToggleModState(KMOD_CAPS, modstate & input->xkb.idx_caps);
|
||||
|
||||
if (group == input->xkb.current_group) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The layout changed, remap and fire an event */
|
||||
input->xkb.current_group = group;
|
||||
keymap.layout = group;
|
||||
SDL_GetDefaultKeymap(keymap.keymap);
|
||||
WAYLAND_xkb_keymap_key_for_each(input->xkb.keymap,
|
||||
|
|
@ -1646,6 +1686,363 @@ Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_type(void* data, struct zwp_tablet_tool_v2* tool, uint32_t type)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_hardware_serial(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial_hi, uint32_t serial_lo)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_hardware_id_wacom(void* data, struct zwp_tablet_tool_v2* tool, uint32_t id_hi, uint32_t id_lo)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_capability(void* data, struct zwp_tablet_tool_v2* tool, uint32_t capability)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_done(void* data, struct zwp_tablet_tool_v2* tool)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_removed(void* data, struct zwp_tablet_tool_v2* tool)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_proximity_in(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial, struct zwp_tablet_v2* tablet, struct wl_surface* surface)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
SDL_WindowData* window;
|
||||
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SDL_WAYLAND_own_surface(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
window = (SDL_WindowData*)wl_surface_get_user_data(surface);
|
||||
|
||||
if (window) {
|
||||
input->tool_focus = window;
|
||||
input->tool_prox_serial = serial;
|
||||
|
||||
input->is_down = SDL_FALSE;
|
||||
|
||||
input->btn_stylus = SDL_FALSE;
|
||||
input->btn_stylus2 = SDL_FALSE;
|
||||
input->btn_stylus3 = SDL_FALSE;
|
||||
|
||||
SDL_SetMouseFocus(window->sdlwindow);
|
||||
SDL_SetCursor(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_proximity_out(void* data, struct zwp_tablet_tool_v2* tool)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
|
||||
if (input->tool_focus) {
|
||||
SDL_SetMouseFocus(NULL);
|
||||
input->tool_focus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tablet_tool_btn_to_sdl_button(struct SDL_WaylandTabletInput* input)
|
||||
{
|
||||
unsigned int tool_btn = input->btn_stylus3 << 2 | input->btn_stylus2 << 1 | input->btn_stylus << 0;
|
||||
switch (tool_btn) {
|
||||
case 0b000:
|
||||
return SDL_BUTTON_LEFT;
|
||||
case 0b001:
|
||||
return SDL_BUTTON_RIGHT;
|
||||
case 0b010:
|
||||
return SDL_BUTTON_MIDDLE;
|
||||
case 0b100:
|
||||
return SDL_BUTTON_X1;
|
||||
default:
|
||||
return SDL_BUTTON_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_down(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
SDL_WindowData* window = input->tool_focus;
|
||||
input->is_down = SDL_TRUE;
|
||||
if (!window) {
|
||||
/* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd.
|
||||
* that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still
|
||||
* received. To prevent SIGSEGV this returns when this is the case.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SendMouseButton(window->sdlwindow, 0, SDL_PRESSED, tablet_tool_btn_to_sdl_button(input));
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_up(void* data, struct zwp_tablet_tool_v2* tool)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
SDL_WindowData* window = input->tool_focus;
|
||||
|
||||
input->is_down = SDL_FALSE;
|
||||
|
||||
if (!window) {
|
||||
/* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd.
|
||||
* that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still
|
||||
* received. To prevent SIGSEGV this returns when this is the case.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SendMouseButton(window->sdlwindow, 0, SDL_RELEASED, tablet_tool_btn_to_sdl_button(input));
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_motion(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
SDL_WindowData* window = input->tool_focus;
|
||||
|
||||
input->sx_w = sx_w;
|
||||
input->sy_w = sy_w;
|
||||
if (input->tool_focus) {
|
||||
const float sx_f = (float)wl_fixed_to_double(sx_w);
|
||||
const float sy_f = (float)wl_fixed_to_double(sy_w);
|
||||
const int sx = (int)SDL_floorf(sx_f * window->pointer_scale_x);
|
||||
const int sy = (int)SDL_floorf(sy_f * window->pointer_scale_y);
|
||||
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_pressure(void* data, struct zwp_tablet_tool_v2* tool, uint32_t pressure)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_distance(void* data, struct zwp_tablet_tool_v2* tool, uint32_t distance)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_tilt(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t xtilt, wl_fixed_t ytilt)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_button(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial, uint32_t button, uint32_t state)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
|
||||
if (input->is_down) {
|
||||
tablet_tool_handle_up(data, tool);
|
||||
input->is_down = SDL_TRUE;
|
||||
}
|
||||
|
||||
switch (button) {
|
||||
/* see %{_includedir}/linux/input-event-codes.h */
|
||||
case 0x14b: /* BTN_STYLUS */
|
||||
input->btn_stylus = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
|
||||
break;
|
||||
case 0x14c: /* BTN_STYLUS2 */
|
||||
input->btn_stylus2 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
|
||||
break;
|
||||
case 0x149: /* BTN_STYLUS3 */
|
||||
input->btn_stylus3 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (input->is_down) {
|
||||
tablet_tool_handle_down(data, tool, serial);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_rotation(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t degrees)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_slider(void* data, struct zwp_tablet_tool_v2* tool, int32_t position)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_wheel(void* data, struct zwp_tablet_tool_v2* tool, int32_t degrees, int32_t clicks)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_tool_handle_frame(void* data, struct zwp_tablet_tool_v2* tool, uint32_t time)
|
||||
{
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
|
||||
static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
|
||||
tablet_tool_handle_type,
|
||||
tablet_tool_handle_hardware_serial,
|
||||
tablet_tool_handle_hardware_id_wacom,
|
||||
tablet_tool_handle_capability,
|
||||
tablet_tool_handle_done,
|
||||
tablet_tool_handle_removed,
|
||||
tablet_tool_handle_proximity_in,
|
||||
tablet_tool_handle_proximity_out,
|
||||
tablet_tool_handle_down,
|
||||
tablet_tool_handle_up,
|
||||
tablet_tool_handle_motion,
|
||||
tablet_tool_handle_pressure,
|
||||
tablet_tool_handle_distance,
|
||||
tablet_tool_handle_tilt,
|
||||
tablet_tool_handle_rotation,
|
||||
tablet_tool_handle_slider,
|
||||
tablet_tool_handle_wheel,
|
||||
tablet_tool_handle_button,
|
||||
tablet_tool_handle_frame
|
||||
};
|
||||
|
||||
struct SDL_WaylandTabletObjectListNode*
|
||||
tablet_object_list_new_node(void* object)
|
||||
{
|
||||
struct SDL_WaylandTabletObjectListNode* node;
|
||||
|
||||
node = SDL_calloc(1, sizeof *node);
|
||||
if (node == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->next = NULL;
|
||||
node->object = object;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void tablet_object_list_append(struct SDL_WaylandTabletObjectListNode* head, void* object)
|
||||
{
|
||||
if (head->object == NULL) {
|
||||
head->object = object;
|
||||
return;
|
||||
}
|
||||
|
||||
while (head->next) {
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
head->next = tablet_object_list_new_node(object);
|
||||
}
|
||||
|
||||
void tablet_object_list_destroy(struct SDL_WaylandTabletObjectListNode* head, void (*deleter)(void* object))
|
||||
{
|
||||
while (head) {
|
||||
struct SDL_WaylandTabletObjectListNode* next = head->next;
|
||||
if (head->object) {
|
||||
(*deleter)(head->object);
|
||||
}
|
||||
SDL_free(head);
|
||||
head = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tablet_seat_handle_tablet_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_v2* tablet)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
|
||||
tablet_object_list_append(input->tablets, tablet);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_seat_handle_tool_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_tool_v2* tool)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
|
||||
zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, data);
|
||||
zwp_tablet_tool_v2_set_user_data(tool, data);
|
||||
|
||||
tablet_object_list_append(input->tools, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
tablet_seat_handle_pad_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_pad_v2* pad)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* input = data;
|
||||
|
||||
tablet_object_list_append(input->pads, pad);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
|
||||
tablet_seat_handle_tablet_added,
|
||||
tablet_seat_handle_tool_added,
|
||||
tablet_seat_handle_pad_added
|
||||
};
|
||||
|
||||
void
|
||||
Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager* tablet_manager)
|
||||
{
|
||||
struct SDL_WaylandTabletInput* tablet_input;
|
||||
|
||||
if (!tablet_manager || !input || !input->seat) {
|
||||
return;
|
||||
}
|
||||
|
||||
tablet_input = SDL_calloc(1, sizeof *tablet_input);
|
||||
if (tablet_input == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
input->tablet = tablet_input;
|
||||
|
||||
tablet_input->seat = (struct SDL_WaylandTabletSeat*)zwp_tablet_manager_v2_get_tablet_seat((struct zwp_tablet_manager_v2*)tablet_manager, input->seat);
|
||||
|
||||
tablet_input->tablets = tablet_object_list_new_node(NULL);
|
||||
tablet_input->tools = tablet_object_list_new_node(NULL);
|
||||
tablet_input->pads = tablet_object_list_new_node(NULL);
|
||||
|
||||
zwp_tablet_seat_v2_add_listener((struct zwp_tablet_seat_v2*)tablet_input->seat, &tablet_seat_listener, tablet_input);
|
||||
}
|
||||
|
||||
#define TABLET_OBJECT_LIST_DELETER(fun) (void (*)(void*))fun
|
||||
void
|
||||
Wayland_input_destroy_tablet(struct SDL_WaylandInput* input)
|
||||
{
|
||||
tablet_object_list_destroy(input->tablet->pads, TABLET_OBJECT_LIST_DELETER(zwp_tablet_pad_v2_destroy));
|
||||
tablet_object_list_destroy(input->tablet->tools, TABLET_OBJECT_LIST_DELETER(zwp_tablet_tool_v2_destroy));
|
||||
tablet_object_list_destroy(input->tablet->tablets, TABLET_OBJECT_LIST_DELETER(zwp_tablet_v2_destroy));
|
||||
|
||||
zwp_tablet_seat_v2_destroy((struct zwp_tablet_seat_v2*)input->tablet->seat);
|
||||
|
||||
SDL_free(input->tablet);
|
||||
input->tablet = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
|
||||
{
|
||||
|
|
@ -1659,6 +2056,7 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
|
|||
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(5, version));
|
||||
input->sx_w = wl_fixed_from_int(0);
|
||||
input->sy_w = wl_fixed_from_int(0);
|
||||
input->xkb.current_group = ~0;
|
||||
d->input = input;
|
||||
|
||||
if (d->data_device_manager != NULL) {
|
||||
|
|
@ -1671,6 +2069,10 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
|
|||
wl_seat_add_listener(input->seat, &seat_listener, input);
|
||||
wl_seat_set_user_data(input->seat, input);
|
||||
|
||||
if (d->tablet_manager) {
|
||||
Wayland_input_add_tablet(input, d->tablet_manager);
|
||||
}
|
||||
|
||||
WAYLAND_wl_display_flush(d->display);
|
||||
}
|
||||
|
||||
|
|
@ -1711,6 +2113,10 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
|
|||
wl_touch_destroy(input->touch);
|
||||
}
|
||||
|
||||
if (input->tablet) {
|
||||
Wayland_input_destroy_tablet(input);
|
||||
}
|
||||
|
||||
if (input->seat)
|
||||
wl_seat_destroy(input->seat);
|
||||
|
||||
|
|
@ -1951,12 +2357,19 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi
|
|||
if (SDL_RectEmpty(&window->mouse_rect)) {
|
||||
confine_rect = NULL;
|
||||
} else {
|
||||
SDL_Rect scaled_mouse_rect;
|
||||
|
||||
scaled_mouse_rect.x = (int)SDL_floorf((float)window->mouse_rect.x / w->pointer_scale_x);
|
||||
scaled_mouse_rect.y = (int)SDL_floorf((float)window->mouse_rect.y / w->pointer_scale_y);
|
||||
scaled_mouse_rect.w = (int)SDL_ceilf((float)window->mouse_rect.w / w->pointer_scale_x);
|
||||
scaled_mouse_rect.h = (int)SDL_ceilf((float)window->mouse_rect.h / w->pointer_scale_y);
|
||||
|
||||
confine_rect = wl_compositor_create_region(d->compositor);
|
||||
wl_region_add(confine_rect,
|
||||
window->mouse_rect.x,
|
||||
window->mouse_rect.y,
|
||||
window->mouse_rect.w,
|
||||
window->mouse_rect.h);
|
||||
scaled_mouse_rect.x,
|
||||
scaled_mouse_rect.y,
|
||||
scaled_mouse_rect.w,
|
||||
scaled_mouse_rect.h);
|
||||
}
|
||||
|
||||
confined_pointer =
|
||||
|
|
|
|||
|
|
@ -29,6 +29,34 @@
|
|||
#include "SDL_waylanddatamanager.h"
|
||||
#include "SDL_waylandkeyboard.h"
|
||||
|
||||
struct SDL_WaylandTabletSeat;
|
||||
|
||||
struct SDL_WaylandTabletObjectListNode {
|
||||
void* object;
|
||||
struct SDL_WaylandTabletObjectListNode* next;
|
||||
};
|
||||
|
||||
struct SDL_WaylandTabletInput {
|
||||
struct SDL_WaylandTabletSeat* seat;
|
||||
|
||||
struct SDL_WaylandTabletObjectListNode* tablets;
|
||||
struct SDL_WaylandTabletObjectListNode* tools;
|
||||
struct SDL_WaylandTabletObjectListNode* pads;
|
||||
|
||||
SDL_WindowData *tool_focus;
|
||||
uint32_t tool_prox_serial;
|
||||
|
||||
/* Last motion location */
|
||||
wl_fixed_t sx_w;
|
||||
wl_fixed_t sy_w;
|
||||
|
||||
SDL_bool is_down;
|
||||
|
||||
SDL_bool btn_stylus;
|
||||
SDL_bool btn_stylus2;
|
||||
SDL_bool btn_stylus3;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
// repeat_rate in range of [1, 1000]
|
||||
int32_t repeat_rate;
|
||||
|
|
@ -68,6 +96,17 @@ struct SDL_WaylandInput {
|
|||
struct xkb_state *state;
|
||||
struct xkb_compose_table *compose_table;
|
||||
struct xkb_compose_state *compose_state;
|
||||
|
||||
/* Keyboard layout "group" */
|
||||
uint32_t current_group;
|
||||
|
||||
/* Modifier bitshift values */
|
||||
uint32_t idx_shift;
|
||||
uint32_t idx_ctrl;
|
||||
uint32_t idx_alt;
|
||||
uint32_t idx_gui;
|
||||
uint32_t idx_num;
|
||||
uint32_t idx_caps;
|
||||
} xkb;
|
||||
|
||||
/* information about axis events on current frame */
|
||||
|
|
@ -80,6 +119,8 @@ struct SDL_WaylandInput {
|
|||
} pointer_curr_axis_info;
|
||||
|
||||
SDL_WaylandKeyboardRepeat keyboard_repeat;
|
||||
|
||||
struct SDL_WaylandTabletInput* tablet;
|
||||
};
|
||||
|
||||
extern void Wayland_PumpEvents(_THIS);
|
||||
|
|
@ -107,6 +148,9 @@ extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d);
|
|||
extern int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input);
|
||||
extern int Wayland_input_ungrab_keyboard(SDL_Window *window);
|
||||
|
||||
extern void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager* tablet_manager);
|
||||
extern void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input);
|
||||
|
||||
#endif /* SDL_waylandevents_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@ Wayland_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
|||
data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (w) {
|
||||
*w = window->w * data->scale_factor;
|
||||
*w = data->drawable_width;
|
||||
}
|
||||
|
||||
if (h) {
|
||||
*h = window->h * data->scale_factor;
|
||||
*h = data->drawable_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,21 +72,19 @@ SDL_WAYLAND_SYM(void, wl_list_remove, (struct wl_list *))
|
|||
SDL_WAYLAND_SYM(int, wl_list_length, (const struct wl_list *))
|
||||
SDL_WAYLAND_SYM(int, wl_list_empty, (const struct wl_list *))
|
||||
SDL_WAYLAND_SYM(void, wl_list_insert_list, (struct wl_list *, struct wl_list *))
|
||||
|
||||
/* These functions are available in Wayland >= 1.4 */
|
||||
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_4)
|
||||
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_proxy *, uint32_t opcode, const struct wl_interface *interface, ...))
|
||||
|
||||
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_10)
|
||||
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor_versioned, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...))
|
||||
|
||||
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_18)
|
||||
SDL_WAYLAND_SYM(void, wl_proxy_set_tag, (struct wl_proxy *, const char * const *))
|
||||
SDL_WAYLAND_SYM(const char * const *, wl_proxy_get_tag, (struct wl_proxy *))
|
||||
|
||||
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_20)
|
||||
#if SDL_WAYLAND_CHECK_VERSION(1, 20, 0)
|
||||
/* wayland-scanner 1.20 generates code that will call these, so these are
|
||||
* non-optional when we are compiling against Wayland 1.20. We don't
|
||||
* explicitly call them ourselves, though, so if we are only compiling
|
||||
* against Wayland 1.18, they're unnecessary. */
|
||||
SDL_WAYLAND_SYM(struct wl_proxy*, wl_proxy_marshal_flags, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interfac, uint32_t version, uint32_t flags, ...))
|
||||
SDL_WAYLAND_SYM(struct wl_proxy*, wl_proxy_marshal_array_flags, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, union wl_argument *args))
|
||||
#endif
|
||||
|
||||
SDL_WAYLAND_INTERFACE(wl_seat_interface)
|
||||
SDL_WAYLAND_INTERFACE(wl_surface_interface)
|
||||
|
|
@ -149,6 +147,8 @@ SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
|
|||
xkb_layout_index_t,
|
||||
const xkb_keysym_t **) )
|
||||
SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )
|
||||
SDL_WAYLAND_SYM(uint32_t, xkb_keymap_mod_get_index, (struct xkb_keymap *,
|
||||
const char *) )
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
SDL_WAYLAND_MODULE(WAYLAND_LIBDECOR)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@
|
|||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "text-input-unstable-v3-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
|
@ -59,6 +62,9 @@
|
|||
|
||||
#define WAYLANDVID_DRIVER_NAME "wayland"
|
||||
|
||||
static void
|
||||
display_handle_done(void *data, struct wl_output *output);
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int
|
||||
Wayland_VideoInit(_THIS);
|
||||
|
|
@ -133,32 +139,22 @@ static const char *SDL_WAYLAND_output_tag = "sdl-output";
|
|||
|
||||
void SDL_WAYLAND_register_surface(struct wl_surface *surface)
|
||||
{
|
||||
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
|
||||
wl_proxy_set_tag((struct wl_proxy *)surface, &SDL_WAYLAND_surface_tag);
|
||||
}
|
||||
wl_proxy_set_tag((struct wl_proxy *)surface, &SDL_WAYLAND_surface_tag);
|
||||
}
|
||||
|
||||
void SDL_WAYLAND_register_output(struct wl_output *output)
|
||||
{
|
||||
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
|
||||
wl_proxy_set_tag((struct wl_proxy *)output, &SDL_WAYLAND_output_tag);
|
||||
}
|
||||
wl_proxy_set_tag((struct wl_proxy *)output, &SDL_WAYLAND_output_tag);
|
||||
}
|
||||
|
||||
SDL_bool SDL_WAYLAND_own_surface(struct wl_surface *surface)
|
||||
{
|
||||
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
|
||||
return wl_proxy_get_tag((struct wl_proxy *) surface) == &SDL_WAYLAND_surface_tag;
|
||||
}
|
||||
return SDL_TRUE; /* For older clients we have to assume this is us... */
|
||||
return wl_proxy_get_tag((struct wl_proxy *) surface) == &SDL_WAYLAND_surface_tag;
|
||||
}
|
||||
|
||||
SDL_bool SDL_WAYLAND_own_output(struct wl_output *output)
|
||||
{
|
||||
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
|
||||
return wl_proxy_get_tag((struct wl_proxy *) output) == &SDL_WAYLAND_output_tag;
|
||||
}
|
||||
return SDL_TRUE; /* For older clients we have to assume this is us... */
|
||||
return wl_proxy_get_tag((struct wl_proxy *) output) == &SDL_WAYLAND_output_tag;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -283,6 +279,8 @@ Wayland_CreateDevice(int devindex)
|
|||
|
||||
device->free = Wayland_DeleteDevice;
|
||||
|
||||
device->disable_display_mode_switching = SDL_TRUE;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
|
@ -291,6 +289,155 @@ VideoBootStrap Wayland_bootstrap = {
|
|||
Wayland_CreateDevice
|
||||
};
|
||||
|
||||
static void
|
||||
xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
SDL_WaylandOutputData* driverdata = data;
|
||||
|
||||
driverdata->x = x;
|
||||
driverdata->y = y;
|
||||
driverdata->has_logical_position = SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
SDL_WaylandOutputData* driverdata = data;
|
||||
|
||||
if (driverdata->width != 0 && driverdata->height != 0) {
|
||||
/* FIXME: GNOME has a bug where the logical size does not account for
|
||||
* scale, resulting in bogus viewport sizes.
|
||||
*
|
||||
* Until this is fixed, validate that _some_ kind of scaling is being
|
||||
* done (we can't match exactly because fractional scaling can't be
|
||||
* detected otherwise), then override if necessary.
|
||||
* -flibit
|
||||
*/
|
||||
const float scale = (float) driverdata->width / (float) width;
|
||||
if ((scale == 1.0f) && (driverdata->scale_factor != 1.0f)) {
|
||||
SDL_LogWarn(
|
||||
SDL_LOG_CATEGORY_VIDEO,
|
||||
"xdg_output scale did not match, overriding with wl_output scale"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
driverdata->width = width;
|
||||
driverdata->height = height;
|
||||
driverdata->has_logical_size = SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
|
||||
{
|
||||
SDL_WaylandOutputData* driverdata = data;
|
||||
|
||||
/*
|
||||
* xdg-output.done events are deprecated and only apply below version 3 of the protocol.
|
||||
* A wl-output.done event will be emitted in version 3 or higher.
|
||||
*/
|
||||
if (zxdg_output_v1_get_version(driverdata->xdg_output) < 3) {
|
||||
display_handle_done(data, driverdata->output);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
|
||||
const char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output,
|
||||
const char *description)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||
xdg_output_handle_logical_position,
|
||||
xdg_output_handle_logical_size,
|
||||
xdg_output_handle_done,
|
||||
xdg_output_handle_name,
|
||||
xdg_output_handle_description,
|
||||
};
|
||||
|
||||
static void
|
||||
AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
|
||||
{
|
||||
struct EmulatedMode
|
||||
{
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
/* Resolution lists courtesy of XWayland */
|
||||
const struct EmulatedMode mode_list[] = {
|
||||
/* 16:9 (1.77) */
|
||||
{ 7680, 4320 },
|
||||
{ 6144, 3160 },
|
||||
{ 5120, 2880 },
|
||||
{ 4096, 2304 },
|
||||
{ 3840, 2160 },
|
||||
{ 3200, 1800 },
|
||||
{ 2880, 1620 },
|
||||
{ 2560, 1440 },
|
||||
{ 2048, 1152 },
|
||||
{ 1920, 1080 },
|
||||
{ 1600, 900 },
|
||||
{ 1368, 768 },
|
||||
{ 1280, 720 },
|
||||
{ 864, 486 },
|
||||
|
||||
/* 16:10 (1.6) */
|
||||
{ 2560, 1600 },
|
||||
{ 1920, 1200 },
|
||||
{ 1680, 1050 },
|
||||
{ 1440, 900 },
|
||||
{ 1280, 800 },
|
||||
|
||||
/* 3:2 (1.5) */
|
||||
{ 720, 480 },
|
||||
|
||||
/* 4:3 (1.33) */
|
||||
{ 2048, 1536 },
|
||||
{ 1920, 1440 },
|
||||
{ 1600, 1200 },
|
||||
{ 1440, 1080 },
|
||||
{ 1400, 1050 },
|
||||
{ 1280, 1024 },
|
||||
{ 1280, 960 },
|
||||
{ 1152, 864 },
|
||||
{ 1024, 768 },
|
||||
{ 800, 600 },
|
||||
{ 640, 480 }
|
||||
};
|
||||
|
||||
int i;
|
||||
const int native_width = dpy->display_modes->w;
|
||||
const int native_height = dpy->display_modes->h;
|
||||
|
||||
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
|
||||
/* Only add modes that are smaller than the native mode */
|
||||
if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
|
||||
(mode_list[i].w < native_width && mode_list[i].h == native_height)) {
|
||||
SDL_DisplayMode mode = *dpy->display_modes;
|
||||
|
||||
if (rot_90) {
|
||||
mode.w = mode_list[i].h;
|
||||
mode.h = mode_list[i].w;
|
||||
} else {
|
||||
mode.w = mode_list[i].w;
|
||||
mode.h = mode_list[i].h;
|
||||
}
|
||||
|
||||
SDL_AddDisplayMode(dpy, &mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_handle_geometry(void *data,
|
||||
struct wl_output *output,
|
||||
|
|
@ -307,7 +454,7 @@ display_handle_geometry(void *data,
|
|||
SDL_VideoDisplay *display;
|
||||
int i;
|
||||
|
||||
if (driverdata->done) {
|
||||
if (driverdata->wl_output_done_count) {
|
||||
/* Clear the wl_output ref so Reset doesn't free it */
|
||||
display = SDL_GetDisplay(driverdata->index);
|
||||
for (i = 0; i < display->num_display_modes; i += 1) {
|
||||
|
|
@ -318,11 +465,14 @@ display_handle_geometry(void *data,
|
|||
SDL_ResetDisplayModes(driverdata->index);
|
||||
|
||||
/* The display has officially started over. */
|
||||
driverdata->done = SDL_FALSE;
|
||||
driverdata->wl_output_done_count = 0;
|
||||
}
|
||||
|
||||
driverdata->x = x;
|
||||
driverdata->y = y;
|
||||
/* Apply the change from wl-output only if xdg-output is not supported */
|
||||
if (!driverdata->has_logical_position) {
|
||||
driverdata->x = x;
|
||||
driverdata->y = y;
|
||||
}
|
||||
driverdata->physical_width = physical_width;
|
||||
driverdata->physical_height = physical_height;
|
||||
if (driverdata->index == -1) {
|
||||
|
|
@ -369,36 +519,21 @@ display_handle_mode(void *data,
|
|||
int refresh)
|
||||
{
|
||||
SDL_WaylandOutputData* driverdata = data;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
if (flags & WL_OUTPUT_MODE_CURRENT) {
|
||||
/* Don't rotate this yet, handle_done will do it later */
|
||||
driverdata->width = width;
|
||||
driverdata->height = height;
|
||||
driverdata->refresh = refresh;
|
||||
}
|
||||
driverdata->native_width = width;
|
||||
driverdata->native_height = height;
|
||||
|
||||
/* Note that the width/height are NOT multiplied by scale_factor!
|
||||
* This is intentional and is designed to get the unscaled modes, which is
|
||||
* important for high-DPI games intending to use the display mode as the
|
||||
* target drawable size. The scaled desktop mode will be added at the end
|
||||
* when display_handle_done is called (see below).
|
||||
*/
|
||||
SDL_zero(mode);
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||
mode.w = height;
|
||||
mode.h = width;
|
||||
} else {
|
||||
mode.w = width;
|
||||
mode.h = height;
|
||||
}
|
||||
mode.refresh_rate = (int)SDL_round(refresh / 1000.0); /* mHz to Hz */
|
||||
mode.driverdata = driverdata->output;
|
||||
if (driverdata->index > -1) {
|
||||
SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &mode);
|
||||
} else {
|
||||
SDL_AddDisplayMode(&driverdata->placeholder, &mode);
|
||||
/*
|
||||
* Don't rotate this yet, wl-output coordinates are transformed in
|
||||
* handle_done and xdg-output coordinates are pre-transformed.
|
||||
*/
|
||||
if (!driverdata->has_logical_size) {
|
||||
driverdata->width = width;
|
||||
driverdata->height = height;
|
||||
}
|
||||
|
||||
driverdata->refresh = refresh;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,20 +542,73 @@ display_handle_done(void *data,
|
|||
struct wl_output *output)
|
||||
{
|
||||
SDL_WaylandOutputData* driverdata = data;
|
||||
SDL_DisplayMode mode;
|
||||
SDL_VideoData* video = driverdata->videodata;
|
||||
SDL_DisplayMode native_mode, desktop_mode;
|
||||
SDL_VideoDisplay *dpy;
|
||||
|
||||
if (driverdata->done)
|
||||
/*
|
||||
* When using xdg-output, two wl-output.done events will be emitted:
|
||||
* one at the completion of wl-display and one at the completion of xdg-output.
|
||||
*
|
||||
* All required events must be received before proceeding.
|
||||
*/
|
||||
const int event_await_count = 1 + (driverdata->xdg_output != NULL);
|
||||
|
||||
driverdata->wl_output_done_count = SDL_min(driverdata->wl_output_done_count + 1, event_await_count + 1);
|
||||
|
||||
if (driverdata->wl_output_done_count != event_await_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
driverdata->done = SDL_TRUE;
|
||||
/* The native display resolution */
|
||||
SDL_zero(native_mode);
|
||||
native_mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
|
||||
SDL_zero(mode);
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||
mode.w = driverdata->height / driverdata->scale_factor;
|
||||
mode.h = driverdata->width / driverdata->scale_factor;
|
||||
native_mode.w = driverdata->native_height;
|
||||
native_mode.h = driverdata->native_width;
|
||||
} else {
|
||||
native_mode.w = driverdata->native_width;
|
||||
native_mode.h = driverdata->native_height;
|
||||
}
|
||||
native_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
|
||||
native_mode.driverdata = driverdata->output;
|
||||
|
||||
/* The scaled desktop mode */
|
||||
SDL_zero(desktop_mode);
|
||||
desktop_mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
|
||||
/* Scale the desktop coordinates, if xdg-output isn't present */
|
||||
if (!driverdata->has_logical_size) {
|
||||
driverdata->width /= driverdata->scale_factor;
|
||||
driverdata->height /= driverdata->scale_factor;
|
||||
}
|
||||
|
||||
/* xdg-output dimensions are already transformed, so no need to rotate. */
|
||||
if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) {
|
||||
desktop_mode.w = driverdata->width;
|
||||
desktop_mode.h = driverdata->height;
|
||||
} else {
|
||||
desktop_mode.w = driverdata->height;
|
||||
desktop_mode.h = driverdata->width;
|
||||
}
|
||||
desktop_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
|
||||
desktop_mode.driverdata = driverdata->output;
|
||||
|
||||
/*
|
||||
* The native display mode is only exposed separately from the desktop size if:
|
||||
* the desktop is scaled and the wp_viewporter protocol is supported.
|
||||
*/
|
||||
if (driverdata->scale_factor > 1.0f && video->viewporter != NULL) {
|
||||
if (driverdata->index > -1) {
|
||||
SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &native_mode);
|
||||
} else {
|
||||
SDL_AddDisplayMode(&driverdata->placeholder, &native_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the display DPI */
|
||||
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
|
||||
driverdata->hdpi = driverdata->physical_height ?
|
||||
(((float) driverdata->height) * 25.4f / driverdata->physical_height) :
|
||||
0.0f;
|
||||
|
|
@ -432,9 +620,6 @@ display_handle_done(void *data,
|
|||
((float) driverdata->physical_height) / 25.4f,
|
||||
((float) driverdata->physical_width) / 25.4f);
|
||||
} else {
|
||||
mode.w = driverdata->width / driverdata->scale_factor;
|
||||
mode.h = driverdata->height / driverdata->scale_factor;
|
||||
|
||||
driverdata->hdpi = driverdata->physical_width ?
|
||||
(((float) driverdata->width) * 25.4f / driverdata->physical_width) :
|
||||
0.0f;
|
||||
|
|
@ -446,8 +631,6 @@ display_handle_done(void *data,
|
|||
((float) driverdata->physical_width) / 25.4f,
|
||||
((float) driverdata->physical_height) / 25.4f);
|
||||
}
|
||||
mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
|
||||
mode.driverdata = driverdata->output;
|
||||
|
||||
if (driverdata->index > -1) {
|
||||
dpy = SDL_GetDisplay(driverdata->index);
|
||||
|
|
@ -455,9 +638,14 @@ display_handle_done(void *data,
|
|||
dpy = &driverdata->placeholder;
|
||||
}
|
||||
|
||||
SDL_AddDisplayMode(dpy, &mode);
|
||||
SDL_SetCurrentDisplayMode(dpy, &mode);
|
||||
SDL_SetDesktopDisplayMode(dpy, &mode);
|
||||
SDL_AddDisplayMode(dpy, &desktop_mode);
|
||||
SDL_SetCurrentDisplayMode(dpy, &desktop_mode);
|
||||
SDL_SetDesktopDisplayMode(dpy, &desktop_mode);
|
||||
|
||||
/* Add emulated modes if wp_viewporter is supported. */
|
||||
if (video->viewporter) {
|
||||
AddEmulatedModes(dpy, (driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0);
|
||||
}
|
||||
|
||||
if (driverdata->index == -1) {
|
||||
/* First time getting display info, create the VideoDisplay */
|
||||
|
|
@ -504,11 +692,29 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
|
|||
data->videodata = d;
|
||||
data->output = output;
|
||||
data->registry_id = id;
|
||||
data->scale_factor = 1.0;
|
||||
data->scale_factor = 1.0f;
|
||||
data->index = -1;
|
||||
|
||||
wl_output_add_listener(output, &output_listener, data);
|
||||
SDL_WAYLAND_register_output(output);
|
||||
|
||||
/* Keep a list of outputs for deferred xdg-output initialization. */
|
||||
if (d->output_list != NULL) {
|
||||
SDL_WaylandOutputData *node = (SDL_WaylandOutputData*)d->output_list;
|
||||
|
||||
while (node->next != NULL) {
|
||||
node = (SDL_WaylandOutputData*)node->next;
|
||||
}
|
||||
|
||||
node->next = (struct SDL_WaylandOutputData*)data;
|
||||
} else {
|
||||
d->output_list = (struct SDL_WaylandOutputData*)data;
|
||||
}
|
||||
|
||||
if (data->videodata->xdg_output_manager) {
|
||||
data->xdg_output = zxdg_output_manager_v1_get_xdg_output(data->videodata->xdg_output_manager, output);
|
||||
zxdg_output_v1_add_listener(data->xdg_output, &xdg_output_listener, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -524,6 +730,9 @@ Wayland_free_display(uint32_t id)
|
|||
data = (SDL_WaylandOutputData *) display->driverdata;
|
||||
if (data->registry_id == id) {
|
||||
SDL_DelVideoDisplay(i);
|
||||
if (data->xdg_output) {
|
||||
zxdg_output_v1_destroy(data->xdg_output);
|
||||
}
|
||||
wl_output_destroy(data->output);
|
||||
SDL_free(data);
|
||||
|
||||
|
|
@ -540,6 +749,16 @@ Wayland_free_display(uint32_t id)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Wayland_init_xdg_output(SDL_VideoData *d)
|
||||
{
|
||||
SDL_WaylandOutputData *node;
|
||||
for (node = d->output_list; node != NULL; node = node->next) {
|
||||
node->xdg_output = zxdg_output_manager_v1_get_xdg_output(node->videodata->xdg_output_manager, node->output);
|
||||
zxdg_output_v1_add_listener(node->xdg_output, &xdg_output_listener, node);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||
static void
|
||||
windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager,
|
||||
|
|
@ -600,7 +819,7 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
} else if (SDL_strcmp(interface, "wl_seat") == 0) {
|
||||
Wayland_display_add_input(d, id, version);
|
||||
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
|
||||
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, 1);
|
||||
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 3));
|
||||
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
|
||||
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
|
||||
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
|
|
@ -620,6 +839,17 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
Wayland_add_data_device_manager(d, id, version);
|
||||
} else if (SDL_strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
||||
d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
|
||||
} else if (SDL_strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||
d->tablet_manager = wl_registry_bind(d->registry, id, &zwp_tablet_manager_v2_interface, 1);
|
||||
if (d->input) {
|
||||
Wayland_input_add_tablet(d->input, d->tablet_manager);
|
||||
}
|
||||
} else if (SDL_strcmp(interface, "zxdg_output_manager_v1") == 0) {
|
||||
version = SDL_min(version, 3); /* Versions 1 through 3 are supported. */
|
||||
d->xdg_output_manager = wl_registry_bind(d->registry, id, &zxdg_output_manager_v1_interface, version);
|
||||
Wayland_init_xdg_output(d);
|
||||
} else if (SDL_strcmp(interface, "wp_viewporter") == 0) {
|
||||
d->viewporter = wl_registry_bind(d->registry, id, &wp_viewporter_interface, 1);
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
|
||||
|
|
@ -646,6 +876,29 @@ static const struct wl_registry_listener registry_listener = {
|
|||
display_handle_global,
|
||||
display_remove_global
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
static SDL_bool should_use_libdecor(SDL_VideoData *data)
|
||||
{
|
||||
if (!SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR, SDL_FALSE)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
if (data->decoration_manager) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
Wayland_VideoInit(_THIS)
|
||||
|
|
@ -669,14 +922,8 @@ Wayland_VideoInit(_THIS)
|
|||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
/* Don't have server-side decorations? Try client-side instead. */
|
||||
if (!data->decoration_manager && SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR && SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
|
||||
if (should_use_libdecor(data)) {
|
||||
data->shell.libdecor = libdecor_new(data->display, &libdecor_interface);
|
||||
|
||||
/* If libdecor works, we don't need xdg-shell anymore. */
|
||||
if (data->shell.libdecor && data->shell.xdg) {
|
||||
xdg_wm_base_destroy(data->shell.xdg);
|
||||
data->shell.xdg = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -737,6 +984,10 @@ Wayland_VideoQuit(_THIS)
|
|||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
SDL_VideoDisplay *display = &_this->displays[i];
|
||||
|
||||
if (((SDL_WaylandOutputData*)display->driverdata)->xdg_output) {
|
||||
zxdg_output_v1_destroy(((SDL_WaylandOutputData*)display->driverdata)->xdg_output);
|
||||
}
|
||||
|
||||
wl_output_destroy(((SDL_WaylandOutputData*)display->driverdata)->output);
|
||||
SDL_free(display->driverdata);
|
||||
display->driverdata = NULL;
|
||||
|
|
@ -779,6 +1030,9 @@ Wayland_VideoQuit(_THIS)
|
|||
Wayland_touch_destroy(data);
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
||||
|
||||
if (data->tablet_manager)
|
||||
zwp_tablet_manager_v2_destroy((struct zwp_tablet_manager_v2*)data->tablet_manager);
|
||||
|
||||
if (data->data_device_manager)
|
||||
wl_data_device_manager_destroy(data->data_device_manager);
|
||||
|
||||
|
|
@ -798,6 +1052,14 @@ Wayland_VideoQuit(_THIS)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (data->xdg_output_manager) {
|
||||
zxdg_output_manager_v1_destroy(data->xdg_output_manager);
|
||||
}
|
||||
|
||||
if (data->viewporter) {
|
||||
wp_viewporter_destroy(data->viewporter);
|
||||
}
|
||||
|
||||
if (data->compositor)
|
||||
wl_compositor_destroy(data->compositor);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
struct xkb_context;
|
||||
struct SDL_WaylandInput;
|
||||
struct SDL_WaylandTabletManager;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||
struct SDL_WaylandTouch;
|
||||
|
|
@ -46,6 +47,8 @@ typedef struct {
|
|||
int size;
|
||||
} SDL_WaylandCursorTheme;
|
||||
|
||||
typedef struct SDL_WaylandOutputData SDL_WaylandOutputData;
|
||||
|
||||
typedef struct {
|
||||
SDL_bool initializing;
|
||||
struct wl_display *display;
|
||||
|
|
@ -70,6 +73,8 @@ typedef struct {
|
|||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||
struct xdg_activation_v1 *activation_manager;
|
||||
struct zwp_text_input_manager_v3 *text_input_manager;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
|
||||
EGLDisplay edpy;
|
||||
EGLContext context;
|
||||
|
|
@ -77,6 +82,8 @@ typedef struct {
|
|||
|
||||
struct xkb_context *xkb_context;
|
||||
struct SDL_WaylandInput *input;
|
||||
struct SDL_WaylandTabletManager *tablet_manager;
|
||||
SDL_WaylandOutputData *output_list;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||
struct SDL_WaylandTouch *touch;
|
||||
|
|
@ -89,19 +96,23 @@ typedef struct {
|
|||
int relative_mouse_mode;
|
||||
} SDL_VideoData;
|
||||
|
||||
typedef struct {
|
||||
struct SDL_WaylandOutputData {
|
||||
SDL_VideoData *videodata;
|
||||
struct wl_output *output;
|
||||
struct zxdg_output_v1 *xdg_output;
|
||||
uint32_t registry_id;
|
||||
float scale_factor;
|
||||
int native_width, native_height;
|
||||
int x, y, width, height, refresh, transform;
|
||||
SDL_DisplayOrientation orientation;
|
||||
int physical_width, physical_height;
|
||||
float ddpi, hdpi, vdpi;
|
||||
SDL_bool has_logical_position, has_logical_size;
|
||||
int index;
|
||||
SDL_VideoDisplay placeholder;
|
||||
SDL_bool done;
|
||||
} SDL_WaylandOutputData;
|
||||
int wl_output_done_count;
|
||||
SDL_WaylandOutputData *next;
|
||||
};
|
||||
|
||||
/* Needed here to get wl_surface declaration, fixes GitHub#4594 */
|
||||
#include "SDL_waylanddyn.h"
|
||||
|
|
|
|||
|
|
@ -139,11 +139,11 @@ void Wayland_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
|||
data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (w) {
|
||||
*w = window->w * data->scale_factor;
|
||||
*w = data->drawable_width;
|
||||
}
|
||||
|
||||
if (h) {
|
||||
*h = window->h * data->scale_factor;
|
||||
*h = data->drawable_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,22 +25,294 @@
|
|||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../events/SDL_windowevents_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "SDL_waylandevents_c.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandtouch.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
#endif
|
||||
|
||||
static void
|
||||
GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int *drawable_width, int *drawable_height)
|
||||
{
|
||||
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
|
||||
|
||||
int fs_width, fs_height;
|
||||
int buf_width, buf_height;
|
||||
|
||||
/*
|
||||
* Fullscreen desktop mandates a desktop sized window, so that's what applications will get.
|
||||
* If the application is DPI aware, it will need to handle the transformations between the
|
||||
* differently sized window and backbuffer spaces on its own.
|
||||
*/
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
fs_width = output->width;
|
||||
fs_height = output->height;
|
||||
|
||||
/* If the application is DPI aware, we can expose the true backbuffer size */
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
buf_width = output->native_width;
|
||||
buf_height = output->native_height;
|
||||
} else {
|
||||
buf_width = fs_width;
|
||||
buf_height = fs_height;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If a mode was set, use it, otherwise use the native resolution
|
||||
* for DPI aware apps and the desktop size for legacy apps.
|
||||
*/
|
||||
if (window->fullscreen_mode.w != 0 && window->fullscreen_mode.h != 0) {
|
||||
fs_width = window->fullscreen_mode.w;
|
||||
fs_height = window->fullscreen_mode.h;
|
||||
} else if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
fs_width = output->native_width;
|
||||
fs_height = output->native_height;
|
||||
} else {
|
||||
fs_width = output->width;
|
||||
fs_height = output->height;
|
||||
}
|
||||
|
||||
buf_width = fs_width;
|
||||
buf_height = fs_height;
|
||||
}
|
||||
|
||||
if (width) {
|
||||
*width = fs_width;
|
||||
}
|
||||
if (height) {
|
||||
*height = fs_height;
|
||||
}
|
||||
if (drawable_width) {
|
||||
*drawable_width = buf_width;
|
||||
}
|
||||
if (drawable_height) {
|
||||
*drawable_height = buf_height;
|
||||
}
|
||||
}
|
||||
|
||||
static inline SDL_bool
|
||||
DesktopIsScaled(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
return data->scale_factor != 1.0f;
|
||||
}
|
||||
|
||||
static inline SDL_bool
|
||||
DesktopIsFractionalScaled(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
|
||||
|
||||
if ((output->native_width != (int)(output->width * data->scale_factor) ||
|
||||
output->native_height != (int)(output->height * data->scale_factor))) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
NeedFullscreenViewport(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_VideoData *video = data->waylandData;
|
||||
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
|
||||
|
||||
int fs_width, fs_height;
|
||||
|
||||
GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Fullscreen needs a viewport:
|
||||
* - If the desktop uses fractional scaling
|
||||
* - Fullscreen desktop was not requested OR the window is DPI aware
|
||||
*
|
||||
* - The desktop uses non-fractional scaling
|
||||
* - Fullscreen desktop was NOT requested
|
||||
*
|
||||
* - The desktop is not scaled
|
||||
* - A non-native fullscreen mode was explicitly set by the client
|
||||
*/
|
||||
if (video->viewporter != NULL && (window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||
if (DesktopIsFractionalScaled(window)) {
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP ||
|
||||
(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
} else if (DesktopIsScaled(window)) {
|
||||
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
} else if (fs_width != output->native_width && fs_height != output->native_height) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static inline SDL_bool
|
||||
NeedWindowedViewport(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_VideoData *video = data->waylandData;
|
||||
|
||||
return !(window->flags & SDL_WINDOW_FULLSCREEN) && (video->viewporter != NULL) &&
|
||||
DesktopIsFractionalScaled(window) && (window->flags & SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
}
|
||||
|
||||
/* Never set a fullscreen window size larger than the desktop. */
|
||||
SDL_FORCE_INLINE int
|
||||
GetWindowWidth(SDL_Window *window)
|
||||
{
|
||||
return NeedFullscreenViewport(window) ? ((SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata)->width : window->w;
|
||||
}
|
||||
|
||||
SDL_FORCE_INLINE int
|
||||
GetWindowHeight(SDL_Window *window)
|
||||
{
|
||||
return NeedFullscreenViewport(window) ? ((SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata)->height : window->h;
|
||||
}
|
||||
|
||||
static void
|
||||
GetWindowBufferSize(SDL_Window *window, int *width, int *height)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
|
||||
int buf_width;
|
||||
int buf_height;
|
||||
|
||||
if (NeedWindowedViewport(window)) {
|
||||
const float frac_scale_x = (float)output->native_width / (float)output->width;
|
||||
const float frac_scale_y = (float)output->native_height / (float)output->height;
|
||||
|
||||
buf_width = (int)SDL_lroundf(window->w * frac_scale_x);
|
||||
buf_height = (int)SDL_lroundf(window->h * frac_scale_y);
|
||||
} else { /* Windowed or fullscreen with no viewport */
|
||||
buf_width = window->w * data->scale_factor;
|
||||
buf_height = window->h * data->scale_factor;
|
||||
}
|
||||
|
||||
if (width) {
|
||||
*width = buf_width;
|
||||
}
|
||||
if (height) {
|
||||
*height = buf_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SetViewport(SDL_Window *window, int src_width, int src_height, int dst_width, int dst_height)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *video = wind->waylandData;
|
||||
|
||||
if (video->viewporter) {
|
||||
if (wind->viewport == NULL) {
|
||||
wind->viewport = wp_viewporter_get_viewport(video->viewporter, wind->surface);
|
||||
}
|
||||
|
||||
wp_viewport_set_source(wind->viewport, wl_fixed_from_int(0), wl_fixed_from_int(0), wl_fixed_from_int(src_width), wl_fixed_from_int(src_height));
|
||||
wp_viewport_set_destination(wind->viewport, dst_width, dst_height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UnsetViewport(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
|
||||
if (wind->viewport) {
|
||||
wp_viewport_destroy(wind->viewport);
|
||||
wind->viewport = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ConfigureViewport(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
SDL_VideoData *viddata = data->waylandData;
|
||||
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
|
||||
|
||||
if (NeedFullscreenViewport(window)) {
|
||||
int fs_width, fs_height;
|
||||
int src_width, src_height;
|
||||
|
||||
GetFullScreenDimensions(window, &fs_width, &fs_height, &src_width, &src_height);
|
||||
SetViewport(window, src_width, src_height, output->width, output->height);
|
||||
|
||||
data->damage_region.x = 0;
|
||||
data->damage_region.y = 0;
|
||||
data->damage_region.w = output->width;
|
||||
data->damage_region.h = output->height;
|
||||
|
||||
data->pointer_scale_x = (float)fs_width / (float)output->width;
|
||||
data->pointer_scale_y = (float)fs_height / (float)output->height;
|
||||
} else {
|
||||
if (NeedWindowedViewport(window)) {
|
||||
int src_width, src_height;
|
||||
|
||||
GetWindowBufferSize(window, &src_width, &src_height);
|
||||
SetViewport(window, src_width, src_height, window->w, window->h);
|
||||
} else {
|
||||
UnsetViewport(window);
|
||||
}
|
||||
|
||||
SDL_zero(data->damage_region);
|
||||
|
||||
data->pointer_scale_x = 1.0f;
|
||||
data->pointer_scale_y = 1.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
* If mouse_rect is not empty, re-create the confinement region with the new scale value.
|
||||
* If the pointer is locked to the general surface with unspecified coordinates, it will
|
||||
* be confined to the viewport region, so no update is required.
|
||||
*/
|
||||
if (!SDL_RectEmpty(&window->mouse_rect)) {
|
||||
Wayland_input_confine_pointer(viddata->input, window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SetDrawScale(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
if (NeedFullscreenViewport(window)) {
|
||||
int fs_width, fs_height;
|
||||
|
||||
GetFullScreenDimensions(window, &fs_width, &fs_height, &data->drawable_width, &data->drawable_height);
|
||||
|
||||
/* Set the buffer scale to 1 since a viewport will be used. */
|
||||
wl_surface_set_buffer_scale(data->surface, 1);
|
||||
} else {
|
||||
GetWindowBufferSize(window, &data->drawable_width, &data->drawable_height);
|
||||
|
||||
if (NeedWindowedViewport(window)) {
|
||||
/* Set the buffer scale to 1 since a viewport will be used. */
|
||||
wl_surface_set_buffer_scale(data->surface, 1);
|
||||
} else {
|
||||
wl_surface_set_buffer_scale(data->surface, (int32_t)data->scale_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
|
||||
{
|
||||
|
|
@ -48,6 +320,15 @@ SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
|
|||
SDL_VideoData *viddata = wind->waylandData;
|
||||
int min_width, min_height, max_width, max_height;
|
||||
|
||||
/* Pop-ups don't get to change size */
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
/* ... but we still want to commit, particularly for ShowWindow */
|
||||
if (commit) {
|
||||
wl_surface_commit(wind->surface);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
||||
min_width = 0;
|
||||
min_height = 0;
|
||||
|
|
@ -66,7 +347,7 @@ SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
|
|||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -100,13 +381,22 @@ SetFullscreen(SDL_Window *window, struct wl_output *output, SDL_bool commit)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = wind->waylandData;
|
||||
|
||||
/* Pop-ups don't get to be fullscreened */
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
/* ... but we still want to commit, particularly for ShowWindow */
|
||||
if (commit) {
|
||||
wl_surface_commit(wind->surface);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* The desktop may try to enforce min/max sizes here, so turn them off for
|
||||
* fullscreen and on (if applicable) for windowed
|
||||
*/
|
||||
SetMinMaxDimensions(window, SDL_FALSE);
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -150,6 +440,11 @@ handle_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time)
|
|||
SDL_WindowData *wind = (SDL_WindowData *) data;
|
||||
SDL_AtomicSet(&wind->swap_interval_ready, 1); /* mark window as ready to present again. */
|
||||
|
||||
if (!SDL_RectEmpty(&wind->damage_region)) {
|
||||
wl_surface_damage(wind->surface, wind->damage_region.x, wind->damage_region.y,
|
||||
wind->damage_region.w, wind->damage_region.h);
|
||||
}
|
||||
|
||||
/* reset this callback to fire again once a new frame was presented and compositor wants the next one. */
|
||||
wind->frame_callback = wl_surface_frame(wind->frame_surface_wrapper);
|
||||
wl_callback_destroy(cb);
|
||||
|
|
@ -303,9 +598,14 @@ handle_configure_xdg_toplevel(void *data,
|
|||
* UPDATE: Nope, sure enough a compositor sends 0,0. This is a known bug:
|
||||
* https://bugs.kde.org/show_bug.cgi?id=444962
|
||||
*/
|
||||
if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
|
||||
window->w = width;
|
||||
window->h = height;
|
||||
if (!NeedFullscreenViewport(window)) {
|
||||
if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
|
||||
window->w = width;
|
||||
window->h = height;
|
||||
wind->needs_resize_event = SDL_TRUE;
|
||||
}
|
||||
} else {
|
||||
GetFullScreenDimensions(window, &window->w, &window->h, NULL, NULL);
|
||||
wind->needs_resize_event = SDL_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -329,6 +629,60 @@ static const struct xdg_toplevel_listener toplevel_listener_xdg = {
|
|||
handle_close_xdg_toplevel
|
||||
};
|
||||
|
||||
static void
|
||||
handle_configure_xdg_popup(void *data,
|
||||
struct xdg_popup *xdg_popup,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t width,
|
||||
int32_t height)
|
||||
{
|
||||
/* No-op, we don't use x/y and width/height are fixed-size */
|
||||
}
|
||||
|
||||
static void
|
||||
handle_done_xdg_popup(void *data, struct xdg_popup *xdg_popup)
|
||||
{
|
||||
SDL_WindowData *window = (SDL_WindowData *)data;
|
||||
SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_repositioned_xdg_popup(void *data,
|
||||
struct xdg_popup *xdg_popup,
|
||||
uint32_t token)
|
||||
{
|
||||
/* No-op, configure does all the work we care about */
|
||||
}
|
||||
|
||||
static const struct xdg_popup_listener popup_listener_xdg = {
|
||||
handle_configure_xdg_popup,
|
||||
handle_done_xdg_popup,
|
||||
handle_repositioned_xdg_popup
|
||||
};
|
||||
|
||||
#define TOOLTIP_CURSOR_OFFSET 8 /* FIXME: Arbitrary, eyeballed from X tooltip */
|
||||
|
||||
static int
|
||||
Wayland_PopupWatch(void *data, SDL_Event *event)
|
||||
{
|
||||
if (event->type == SDL_MOUSEMOTION) {
|
||||
SDL_Window *window = (SDL_Window *) data;
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
|
||||
/* Coordinates might be relative to the popup, which we don't want */
|
||||
if (event->motion.windowID == wind->shell_surface.xdg.roleobj.popup.parentID) {
|
||||
xdg_positioner_set_offset(wind->shell_surface.xdg.roleobj.popup.positioner,
|
||||
event->motion.x + TOOLTIP_CURSOR_OFFSET,
|
||||
event->motion.y + TOOLTIP_CURSOR_OFFSET);
|
||||
xdg_popup_reposition(wind->shell_surface.xdg.roleobj.popup.popup,
|
||||
wind->shell_surface.xdg.roleobj.popup.positioner,
|
||||
0);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
static void
|
||||
decoration_frame_configure(struct libdecor_frame *frame,
|
||||
|
|
@ -399,17 +753,23 @@ decoration_frame_configure(struct libdecor_frame *frame,
|
|||
* Always assume the configure is wrong.
|
||||
*/
|
||||
if (fullscreen) {
|
||||
/* FIXME: We have been explicitly told to respect the fullscreen size
|
||||
* parameters here, even though they are known to be wrong on GNOME at
|
||||
* bare minimum. If this is wrong, don't blame us, we were explicitly
|
||||
* told to do this.
|
||||
*/
|
||||
if (!libdecor_configuration_get_content_size(configuration, frame,
|
||||
&width, &height)) {
|
||||
width = window->w;
|
||||
height = window->h;
|
||||
if (!NeedFullscreenViewport(window)) {
|
||||
/* FIXME: We have been explicitly told to respect the fullscreen size
|
||||
* parameters here, even though they are known to be wrong on GNOME at
|
||||
* bare minimum. If this is wrong, don't blame us, we were explicitly
|
||||
* told to do this.
|
||||
*/
|
||||
if (!libdecor_configuration_get_content_size(configuration, frame,
|
||||
&width, &height)) {
|
||||
width = window->w;
|
||||
height = window->h;
|
||||
}
|
||||
} else {
|
||||
GetFullScreenDimensions(window, &width, &height, NULL, NULL);
|
||||
}
|
||||
|
||||
wind->needs_resize_event = SDL_TRUE;
|
||||
|
||||
/* This part is good though. */
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
scale_factor = driverdata->scale_factor;
|
||||
|
|
@ -445,7 +805,7 @@ decoration_frame_configure(struct libdecor_frame *frame,
|
|||
wind->shell_surface.libdecor.initial_configure_seen = SDL_TRUE;
|
||||
|
||||
/* ... then commit the changes on the libdecor side. */
|
||||
state = libdecor_state_new(width, height);
|
||||
state = libdecor_state_new(GetWindowWidth(window), GetWindowHeight(window));
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
|
|
@ -554,9 +914,28 @@ Wayland_move_window(SDL_Window *window,
|
|||
int i, numdisplays = SDL_GetNumVideoDisplays();
|
||||
for (i = 0; i < numdisplays; i += 1) {
|
||||
if (SDL_GetDisplay(i)->driverdata == driverdata) {
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED,
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(i),
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(i));
|
||||
/* We want to send a very very specific combination here:
|
||||
*
|
||||
* 1. A coordinate that tells the application what display we're on
|
||||
* 2. Exactly (0, 0)
|
||||
*
|
||||
* Part 1 is useful information but is also really important for
|
||||
* ensuring we end up on the right display for fullscreen, while
|
||||
* part 2 is important because numerous applications use a specific
|
||||
* combination of GetWindowPosition and GetGlobalMouseState, and of
|
||||
* course neither are supported by Wayland. Since global mouse will
|
||||
* fall back to just GetMouseState, we need the window position to
|
||||
* be zero so the cursor math works without it going off in some
|
||||
* random direction. See UE5 Editor for a notable example of this!
|
||||
*
|
||||
* This may be an issue some day if we're ever able to implement
|
||||
* SDL_GetDisplayUsableBounds!
|
||||
*
|
||||
* -flibit
|
||||
*/
|
||||
SDL_Rect bounds;
|
||||
SDL_GetDisplayBounds(i, &bounds);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, bounds.x, bounds.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -624,6 +1003,19 @@ static const struct wl_surface_listener surface_listener = {
|
|||
handle_surface_leave
|
||||
};
|
||||
|
||||
static void
|
||||
Wayland_FillEmptyShellInfo(SDL_SysWMinfo * info, const Uint32 version)
|
||||
{
|
||||
info->info.wl.xdg_surface = NULL;
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
|
||||
info->info.wl.xdg_toplevel = NULL;
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 22)) {
|
||||
info->info.wl.xdg_popup = NULL;
|
||||
info->info.wl.xdg_positioner = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
||||
{
|
||||
|
|
@ -656,23 +1048,40 @@ Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|||
info->info.wl.egl_window = data->egl_window;
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor && data->shell_surface.libdecor.frame != NULL) {
|
||||
info->info.wl.xdg_surface = libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame);
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
|
||||
info->info.wl.xdg_toplevel = libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame);
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (data->shell_surface.libdecor.frame != NULL) {
|
||||
info->info.wl.xdg_surface = libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame);
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
|
||||
info->info.wl.xdg_toplevel = libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame);
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 22)) {
|
||||
info->info.wl.xdg_popup = NULL;
|
||||
info->info.wl.xdg_positioner = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Not mapped yet */
|
||||
Wayland_FillEmptyShellInfo(info, version);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
|
||||
info->info.wl.xdg_surface = data->shell_surface.xdg.surface;
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
|
||||
info->info.wl.xdg_toplevel = data->shell_surface.xdg.roleobj.toplevel;
|
||||
SDL_bool popup = WINDOW_IS_XDG_POPUP(window);
|
||||
info->info.wl.xdg_toplevel = popup ? NULL : data->shell_surface.xdg.roleobj.toplevel;
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 22)) {
|
||||
if (popup) {
|
||||
info->info.wl.xdg_popup = data->shell_surface.xdg.roleobj.popup.popup;
|
||||
info->info.wl.xdg_positioner = data->shell_surface.xdg.roleobj.popup.positioner;
|
||||
} else {
|
||||
info->info.wl.xdg_popup = NULL;
|
||||
info->info.wl.xdg_positioner = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info->info.wl.xdg_surface = NULL;
|
||||
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
|
||||
info->info.wl.xdg_toplevel = NULL;
|
||||
}
|
||||
/* Either it's not mapped yet or we don't have a shell protocol */
|
||||
Wayland_FillEmptyShellInfo(info, version);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -697,6 +1106,10 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
|
|||
SDL_WindowData *modal_data = modal_window->driverdata;
|
||||
SDL_WindowData *parent_data = parent_window->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(modal_window) || WINDOW_IS_XDG_POPUP(parent_window)) {
|
||||
return SDL_SetError("Modal/Parent was a popup, not a toplevel");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (modal_data->shell_surface.libdecor.frame == NULL) {
|
||||
|
|
@ -731,9 +1144,26 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
SDL_VideoData *c = _this->driverdata;
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
|
||||
/* Create the shell surface and map the toplevel */
|
||||
/* Detach any previous buffers before resetting everything, otherwise when
|
||||
* calling this a second time you'll get an annoying protocol error!
|
||||
*
|
||||
* FIXME: This was originally moved to HideWindow, which _should_ make
|
||||
* sense, but for whatever reason UE5's popups require that this actually
|
||||
* be in both places at once? Possibly from renderers making commits? I can't
|
||||
* fully remember if this location caused crashes or if I was fixing a pair
|
||||
* of Hide/Show calls. In any case, UE gives us a pretty good test and having
|
||||
* both detach calls passes. This bug may be relevant if I'm wrong:
|
||||
*
|
||||
* https://bugs.kde.org/show_bug.cgi?id=448856
|
||||
*
|
||||
* -flibit
|
||||
*/
|
||||
wl_surface_attach(data->surface, NULL, 0, 0);
|
||||
wl_surface_commit(data->surface);
|
||||
|
||||
/* Create the shell surface and map the toplevel/popup */
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (c->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(c, window)) {
|
||||
data->shell_surface.libdecor.frame = libdecor_decorate(c->shell.libdecor,
|
||||
data->surface,
|
||||
&libdecor_frame_interface,
|
||||
|
|
@ -751,10 +1181,42 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
|
||||
xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
|
||||
|
||||
/* !!! FIXME: add popup role */
|
||||
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
|
||||
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
|
||||
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Window *focused = SDL_GetMouseFocus();
|
||||
SDL_WindowData *focuseddata = focused->driverdata;
|
||||
|
||||
/* This popup may be a child of another popup! */
|
||||
data->shell_surface.xdg.roleobj.popup.parentID = SDL_GetWindowID(focused);
|
||||
data->shell_surface.xdg.roleobj.popup.child = NULL;
|
||||
if (WINDOW_IS_XDG_POPUP(focused)) {
|
||||
SDL_assert(focuseddata->shell_surface.xdg.roleobj.popup.child == NULL);
|
||||
focuseddata->shell_surface.xdg.roleobj.popup.child = window;
|
||||
}
|
||||
|
||||
/* Set up the positioner for the popup */
|
||||
data->shell_surface.xdg.roleobj.popup.positioner = xdg_wm_base_create_positioner(c->shell.xdg);
|
||||
xdg_positioner_set_offset(data->shell_surface.xdg.roleobj.popup.positioner,
|
||||
mouse->x + TOOLTIP_CURSOR_OFFSET,
|
||||
mouse->y + TOOLTIP_CURSOR_OFFSET);
|
||||
|
||||
/* Assign the popup role */
|
||||
data->shell_surface.xdg.roleobj.popup.popup = xdg_surface_get_popup(data->shell_surface.xdg.surface,
|
||||
focuseddata->shell_surface.xdg.surface,
|
||||
data->shell_surface.xdg.roleobj.popup.positioner);
|
||||
xdg_popup_add_listener(data->shell_surface.xdg.roleobj.popup.popup, &popup_listener_xdg, data);
|
||||
|
||||
/* For tooltips, track mouse motion so it follows the cursor */
|
||||
if (window->flags & SDL_WINDOW_TOOLTIP) {
|
||||
if (xdg_popup_get_version(data->shell_surface.xdg.roleobj.popup.popup) >= 3) {
|
||||
SDL_AddEventWatch(Wayland_PopupWatch, window);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
|
||||
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
|
||||
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore state that was set prior to this call */
|
||||
|
|
@ -770,7 +1232,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
* this surface will fail. This is a new rule for xdg_shell.
|
||||
*/
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (c->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(c, window)) {
|
||||
if (data->shell_surface.libdecor.frame) {
|
||||
while (!data->shell_surface.libdecor.initial_configure_seen) {
|
||||
WAYLAND_wl_display_flush(c->display);
|
||||
|
|
@ -794,7 +1256,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
|
||||
/* Create the window decorations */
|
||||
if (data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
|
||||
if (!WINDOW_IS_XDG_POPUP(window) && data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
|
||||
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -807,11 +1269,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
* them immediately afterward.
|
||||
*/
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (c->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(c, window)) {
|
||||
/* ... but don't call it redundantly for libdecor, the decorator
|
||||
* may not interpret a redundant call nicely and cause weird stuff to happen
|
||||
*/
|
||||
if (window->flags & SDL_WINDOW_BORDERLESS) {
|
||||
if (data->shell_surface.libdecor.frame && window->flags & SDL_WINDOW_BORDERLESS) {
|
||||
Wayland_SetWindowBordered(_this, window, SDL_FALSE);
|
||||
}
|
||||
} else
|
||||
|
|
@ -837,6 +1299,42 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Wayland_ReleasePopup(_THIS, SDL_Window *popup)
|
||||
{
|
||||
SDL_WindowData *popupdata;
|
||||
|
||||
/* Basic sanity checks to weed out the weird popup closures */
|
||||
if (popup == NULL || popup->magic != &_this->window_magic) {
|
||||
return;
|
||||
}
|
||||
popupdata = popup->driverdata;
|
||||
if (popupdata == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This may already be freed by a parent popup! */
|
||||
if (popupdata->shell_surface.xdg.roleobj.popup.popup == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release the child _first_, otherwise a protocol error triggers */
|
||||
if (popupdata->shell_surface.xdg.roleobj.popup.child != NULL) {
|
||||
Wayland_ReleasePopup(_this, popupdata->shell_surface.xdg.roleobj.popup.child);
|
||||
popupdata->shell_surface.xdg.roleobj.popup.child = NULL;
|
||||
}
|
||||
|
||||
if (popup->flags & SDL_WINDOW_TOOLTIP) {
|
||||
if (xdg_popup_get_version(popupdata->shell_surface.xdg.roleobj.popup.popup) >= 3) {
|
||||
SDL_DelEventWatch(Wayland_PopupWatch, popup);
|
||||
}
|
||||
}
|
||||
xdg_popup_destroy(popupdata->shell_surface.xdg.roleobj.popup.popup);
|
||||
xdg_positioner_destroy(popupdata->shell_surface.xdg.roleobj.popup.positioner);
|
||||
popupdata->shell_surface.xdg.roleobj.popup.popup = NULL;
|
||||
popupdata->shell_surface.xdg.roleobj.popup.positioner = NULL;
|
||||
}
|
||||
|
||||
void Wayland_HideWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
|
|
@ -848,7 +1346,7 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (data->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(data, window)) {
|
||||
if (wind->shell_surface.libdecor.frame) {
|
||||
libdecor_frame_unref(wind->shell_surface.libdecor.frame);
|
||||
wind->shell_surface.libdecor.frame = NULL;
|
||||
|
|
@ -856,7 +1354,9 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
|
|||
} else
|
||||
#endif
|
||||
if (data->shell.xdg) {
|
||||
if (wind->shell_surface.xdg.roleobj.toplevel) {
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
Wayland_ReleasePopup(_this, window);
|
||||
} else if (wind->shell_surface.xdg.roleobj.toplevel) {
|
||||
xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
|
||||
wind->shell_surface.xdg.roleobj.toplevel = NULL;
|
||||
}
|
||||
|
|
@ -1073,13 +1573,17 @@ Wayland_RestoreWindow(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set this flag now even if we never actually maximized, eventually
|
||||
* ShowWindow will take care of it along with the other window state.
|
||||
*/
|
||||
window->flags &= ~SDL_WINDOW_MAXIMIZED;
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -1102,8 +1606,13 @@ Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
|
|||
{
|
||||
SDL_WindowData *wind = window->driverdata;
|
||||
const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame) {
|
||||
libdecor_frame_set_visibility(wind->shell_surface.libdecor.frame, bordered);
|
||||
}
|
||||
|
|
@ -1122,7 +1631,7 @@ Wayland_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
|
|||
SDL_VideoData *data = _this->driverdata;
|
||||
const SDL_WindowData *wind = window->driverdata;
|
||||
|
||||
if (data->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(data, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -1144,6 +1653,10 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1154,7 +1667,7 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
|
|||
window->flags |= SDL_WINDOW_MAXIMIZED;
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -1177,8 +1690,12 @@ Wayland_MinimizeWindow(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -1269,7 +1786,9 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
data->waylandData = c;
|
||||
data->sdlwindow = window;
|
||||
|
||||
data->scale_factor = 1.0;
|
||||
data->scale_factor = 1.0f;
|
||||
data->pointer_scale_x = 1.0f;
|
||||
data->pointer_scale_y = 1.0f;
|
||||
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
int i;
|
||||
|
|
@ -1316,16 +1835,18 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
||||
|
||||
data->drawable_width = window->w * data->scale_factor;
|
||||
data->drawable_height = window->h * data->scale_factor;
|
||||
|
||||
if (window->flags & SDL_WINDOW_OPENGL) {
|
||||
data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
|
||||
window->w * data->scale_factor, window->h * data->scale_factor);
|
||||
data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
|
||||
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
/* Create the GLES window surface */
|
||||
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
|
||||
|
||||
if (data->egl_surface == EGL_NO_SURFACE) {
|
||||
return SDL_SetError("failed to create an EGL window surface");
|
||||
return -1; /* SDL_EGL_CreateSurface should have set error */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1375,12 +1896,13 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
|
|||
data->needs_resize_event = SDL_FALSE;
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_scale(data->surface, data->scale_factor);
|
||||
/* Configure the backbuffer size and scale factors */
|
||||
SetDrawScale(window);
|
||||
|
||||
if (data->egl_window) {
|
||||
WAYLAND_wl_egl_window_resize(data->egl_window,
|
||||
window->w * data->scale_factor,
|
||||
window->h * data->scale_factor,
|
||||
data->drawable_width,
|
||||
data->drawable_height,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1394,9 +1916,18 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
|
|||
* It doesn't fix the first frames after resize being glitched visually,
|
||||
* but at least lets us not be terminated by the compositor.
|
||||
* Can be removed once SDL's resize logic becomes compliant. */
|
||||
if (viddata->shell.xdg && data->shell_surface.xdg.surface) {
|
||||
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, window->w, window->h);
|
||||
if (
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
!WINDOW_IS_LIBDECOR(viddata, window) &&
|
||||
#endif
|
||||
viddata->shell.xdg &&
|
||||
data->shell_surface.xdg.surface) {
|
||||
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0,
|
||||
GetWindowWidth(window), GetWindowHeight(window));
|
||||
}
|
||||
|
||||
/* Update the viewport */
|
||||
ConfigureViewport(window);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1422,7 +1953,7 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
|
|||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
/* we must not resize the window while we have a static (non-floating) size */
|
||||
if (data->shell.libdecor &&
|
||||
if (WINDOW_IS_LIBDECOR(data, window) &&
|
||||
wind->shell_surface.libdecor.frame &&
|
||||
!libdecor_frame_is_floating(wind->shell_surface.libdecor.frame)) {
|
||||
/* Commit the resize when we re-enter floating state */
|
||||
|
|
@ -1431,18 +1962,18 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
|
|||
}
|
||||
#endif
|
||||
|
||||
wl_surface_set_buffer_scale(wind->surface, wind->scale_factor);
|
||||
SetDrawScale(window);
|
||||
|
||||
if (wind->egl_window) {
|
||||
WAYLAND_wl_egl_window_resize(wind->egl_window,
|
||||
window->w * wind->scale_factor,
|
||||
window->h * wind->scale_factor,
|
||||
wind->drawable_width,
|
||||
wind->drawable_height,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (data->shell.libdecor && wind->shell_surface.libdecor.frame) {
|
||||
state = libdecor_state_new(window->w, window->h);
|
||||
if (WINDOW_IS_LIBDECOR(data, window) && wind->shell_surface.libdecor.frame) {
|
||||
state = libdecor_state_new(GetWindowWidth(window), GetWindowHeight(window));
|
||||
libdecor_frame_commit(wind->shell_surface.libdecor.frame, state, NULL);
|
||||
libdecor_state_free(state);
|
||||
}
|
||||
|
|
@ -1458,8 +1989,14 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
|
|||
wl_region_destroy(region);
|
||||
|
||||
/* Update the geometry which may have been set by a hack in Wayland_HandleResize */
|
||||
if (data->shell.xdg && wind->shell_surface.xdg.surface) {
|
||||
xdg_surface_set_window_geometry(wind->shell_surface.xdg.surface, 0, 0, window->w, window->h);
|
||||
if (
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
!WINDOW_IS_LIBDECOR(data, window) &&
|
||||
#endif
|
||||
data->shell.xdg &&
|
||||
wind->shell_surface.xdg.surface) {
|
||||
xdg_surface_set_window_geometry(wind->shell_surface.xdg.surface, 0, 0,
|
||||
GetWindowWidth(window), GetWindowHeight(window));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1468,9 +2005,13 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
|
|||
SDL_WindowData *wind = window->driverdata;
|
||||
SDL_VideoData *viddata = _this->driverdata;
|
||||
|
||||
if (WINDOW_IS_XDG_POPUP(window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->title != NULL) {
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
if (viddata->shell.libdecor) {
|
||||
if (WINDOW_IS_LIBDECOR(viddata, window)) {
|
||||
if (wind->shell_surface.libdecor.frame == NULL) {
|
||||
return; /* Can't do anything yet, wait for ShowWindow */
|
||||
}
|
||||
|
|
@ -1549,6 +2090,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
|
|||
xdg_activation_token_v1_destroy(wind->activation_token);
|
||||
}
|
||||
|
||||
if (wind->viewport) {
|
||||
wp_viewport_destroy(wind->viewport);
|
||||
}
|
||||
|
||||
SDL_free(wind->outputs);
|
||||
|
||||
if (wind->frame_callback) {
|
||||
|
|
|
|||
|
|
@ -36,16 +36,27 @@ typedef struct {
|
|||
struct xdg_surface *surface;
|
||||
union {
|
||||
struct xdg_toplevel *toplevel;
|
||||
struct xdg_popup *popup;
|
||||
struct {
|
||||
struct xdg_popup *popup;
|
||||
struct xdg_positioner *positioner;
|
||||
Uint32 parentID;
|
||||
SDL_Window *child;
|
||||
} popup;
|
||||
} roleobj;
|
||||
SDL_bool initial_configure_seen;
|
||||
} SDL_xdg_shell_surface;
|
||||
|
||||
#define WINDOW_IS_XDG_POPUP(window) \
|
||||
(window->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU))
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
typedef struct {
|
||||
struct libdecor_frame *frame;
|
||||
SDL_bool initial_configure_seen;
|
||||
} SDL_libdecor_surface;
|
||||
|
||||
#define WINDOW_IS_LIBDECOR(viddata, window) \
|
||||
(viddata->shell.libdecor && !WINDOW_IS_XDG_POPUP(window))
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -72,6 +83,7 @@ typedef struct {
|
|||
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
|
||||
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||
struct xdg_activation_token_v1 *activation_token;
|
||||
struct wp_viewport *viewport;
|
||||
|
||||
/* floating dimensions for restoring from maximized and fullscreen */
|
||||
int floating_width, floating_height;
|
||||
|
|
@ -86,6 +98,10 @@ typedef struct {
|
|||
int num_outputs;
|
||||
|
||||
float scale_factor;
|
||||
float pointer_scale_x;
|
||||
float pointer_scale_y;
|
||||
int drawable_width, drawable_height;
|
||||
SDL_Rect damage_region;
|
||||
SDL_bool needs_resize_event;
|
||||
SDL_bool floating_resize_pending;
|
||||
} SDL_WindowData;
|
||||
|
|
|
|||
|
|
@ -378,14 +378,14 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
|
|||
}
|
||||
|
||||
static void
|
||||
WIN_UpdateFocus(SDL_Window *window)
|
||||
WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
HWND hwnd = data->hwnd;
|
||||
SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
|
||||
SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
if (had_focus == has_focus) {
|
||||
if (had_focus == has_focus || has_focus != expect_focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +686,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
|
||||
actually being the foreground window, but this appears to get called in all cases where
|
||||
the global foreground window changes to and from this window. */
|
||||
WIN_UpdateFocus(data->window);
|
||||
WIN_UpdateFocus(data->window, !!wParam);
|
||||
WIN_CheckICMProfileChanged(data->window);
|
||||
}
|
||||
break;
|
||||
|
|
@ -694,16 +694,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
case WM_ACTIVATE:
|
||||
{
|
||||
/* Update the focus in case we changed focus to a child window and then away from the application */
|
||||
WIN_UpdateFocus(data->window);
|
||||
WIN_UpdateFocus(data->window, !!LOWORD(wParam));
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
/* Update the focus in case it's changing between top-level windows in the same application */
|
||||
WIN_UpdateFocus(data->window, SDL_TRUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
case WM_ENTERIDLE:
|
||||
{
|
||||
/* Update the focus in case it's changing between top-level windows in the same application */
|
||||
WIN_UpdateFocus(data->window);
|
||||
WIN_UpdateFocus(data->window, SDL_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
|
|||
int w, h;
|
||||
|
||||
/* Figure out what the window area will be */
|
||||
if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || (window->flags & SDL_WINDOW_ALWAYS_ON_TOP))) {
|
||||
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
|
||||
top = HWND_TOPMOST;
|
||||
} else {
|
||||
top = HWND_NOTOPMOST;
|
||||
|
|
@ -734,7 +734,14 @@ WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display,
|
|||
int x, y;
|
||||
int w, h;
|
||||
|
||||
if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
|
||||
if (!fullscreen && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
|
||||
/* Resizing the window on hide causes problems restoring it in Wine, and it's unnecessary.
|
||||
* Also, Windows would preview the minimized window with the wrong size.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
|
||||
top = HWND_TOPMOST;
|
||||
} else {
|
||||
top = HWND_NOTOPMOST;
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ X11_GetScrollLockModifierMask(_THIS)
|
|||
return num_mask;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
X11_ReconcileKeyboardState(_THIS)
|
||||
{
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
|
|
@ -408,7 +408,22 @@ X11_ReconcileKeyboardState(_THIS)
|
|||
SDL_bool sdlKeyPressed = keyboardState[scancode] == SDL_PRESSED;
|
||||
|
||||
if (x11KeyPressed && !sdlKeyPressed) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
/* Only update modifier state for keys that are pressed in another application */
|
||||
switch (SDL_GetKeyFromScancode(scancode)) {
|
||||
case SDLK_LCTRL:
|
||||
case SDLK_RCTRL:
|
||||
case SDLK_LSHIFT:
|
||||
case SDLK_RSHIFT:
|
||||
case SDLK_LALT:
|
||||
case SDLK_RALT:
|
||||
case SDLK_LGUI:
|
||||
case SDLK_RGUI:
|
||||
case SDLK_MODE:
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (!x11KeyPressed && sdlKeyPressed) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
|
|
@ -718,7 +733,6 @@ static void
|
|||
X11_DispatchEvent(_THIS, XEvent *xevent)
|
||||
{
|
||||
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
||||
XkbEvent* xkbEvent = (XkbEvent*) xevent;
|
||||
Display *display;
|
||||
SDL_WindowData *data;
|
||||
int orig_event_type;
|
||||
|
|
@ -805,11 +819,13 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||
if (!data) {
|
||||
/* The window for KeymapNotify, etc events is 0 */
|
||||
if (xevent->type == KeymapNotify) {
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: KeymapNotify!\n", data);
|
||||
#endif
|
||||
if (SDL_GetKeyboardFocus() != NULL) {
|
||||
X11_ReconcileKeyboardState(_this);
|
||||
}
|
||||
} else if (xevent->type == MappingNotify ||
|
||||
(xevent->type == videodata->xkb_event && xkbEvent->any.xkb_type == XkbStateNotify)) {
|
||||
} else if (xevent->type == MappingNotify) {
|
||||
/* Has the keyboard layout changed? */
|
||||
const int request = xevent->xmapping.request;
|
||||
|
||||
|
|
@ -996,8 +1012,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||
}
|
||||
break;
|
||||
|
||||
/* Key press? */
|
||||
case KeyPress:{
|
||||
/* Key press/release? */
|
||||
case KeyPress:
|
||||
case KeyRelease: {
|
||||
KeyCode keycode = xevent->xkey.keycode;
|
||||
KeySym keysym = NoSymbol;
|
||||
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
|
||||
|
|
@ -1005,7 +1022,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||
SDL_bool handled_by_ime = SDL_FALSE;
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
|
||||
printf("window %p: %s (X11 keycode = 0x%X)\n", data, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode);
|
||||
#endif
|
||||
#if 1
|
||||
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
|
||||
|
|
@ -1021,7 +1038,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||
/* */
|
||||
SDL_zeroa(text);
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
if (data->ic) {
|
||||
if (data->ic && xevent->type == KeyPress) {
|
||||
X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
|
||||
&keysym, &status);
|
||||
} else {
|
||||
|
|
@ -1033,35 +1050,30 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||
|
||||
#ifdef SDL_USE_IME
|
||||
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
|
||||
handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
|
||||
handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED));
|
||||
}
|
||||
#endif
|
||||
if (!handled_by_ime) {
|
||||
/* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
|
||||
if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
|
||||
}
|
||||
if(*text) {
|
||||
SDL_SendKeyboardText(text);
|
||||
if (xevent->type == KeyPress) {
|
||||
/* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
|
||||
if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
|
||||
}
|
||||
if(*text) {
|
||||
SDL_SendKeyboardText(text);
|
||||
}
|
||||
} else {
|
||||
if (X11_KeyRepeat(display, xevent)) {
|
||||
/* We're about to get a repeated key down, ignore the key up */
|
||||
break;
|
||||
}
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
|
||||
}
|
||||
}
|
||||
|
||||
X11_UpdateUserTime(data, xevent->xkey.time);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Key release? */
|
||||
case KeyRelease:{
|
||||
KeyCode keycode = xevent->xkey.keycode;
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
|
||||
#endif
|
||||
if (X11_KeyRepeat(display, xevent)) {
|
||||
/* We're about to get a repeated key down, ignore the key up */
|
||||
break;
|
||||
if (xevent->type == KeyPress) {
|
||||
X11_UpdateUserTime(data, xevent->xkey.time);
|
||||
}
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ extern void X11_PumpEvents(_THIS);
|
|||
extern int X11_WaitEventTimeout(_THIS, int timeout);
|
||||
extern void X11_SendWakeupEvent(_THIS, SDL_Window *window);
|
||||
extern void X11_SuspendScreenSaver(_THIS);
|
||||
extern void X11_ReconcileKeyboardState(_THIS);
|
||||
|
||||
#endif /* SDL_x11events_h_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -409,6 +409,8 @@ X11_InitKeyboard(_THIS)
|
|||
SDL_IME_Init();
|
||||
#endif
|
||||
|
||||
X11_ReconcileKeyboardState(_this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -830,10 +830,11 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
int exitcode = 0;
|
||||
close(fds[0]);
|
||||
status = X11_ShowMessageBoxImpl(messageboxdata, buttonid);
|
||||
if (write(fds[1], &status, sizeof (int)) != sizeof (int))
|
||||
if (write(fds[1], &status, sizeof (int)) != sizeof (int)) {
|
||||
exitcode = 1;
|
||||
else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int))
|
||||
} else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int)) {
|
||||
exitcode = 1;
|
||||
}
|
||||
close(fds[1]);
|
||||
_exit(exitcode); /* don't run atexit() stuff, static destructors, etc. */
|
||||
} else { /* we're the parent */
|
||||
|
|
@ -846,13 +847,12 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
SDL_assert(rc == pid); /* not sure what to do if this fails. */
|
||||
|
||||
if ((rc == -1) || (!WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) {
|
||||
return SDL_SetError("msgbox child process failed");
|
||||
status = SDL_SetError("msgbox child process failed");
|
||||
} else if ( (read(fds[0], &status, sizeof (int)) != sizeof (int)) ||
|
||||
(read(fds[0], buttonid, sizeof (int)) != sizeof (int)) ) {
|
||||
status = SDL_SetError("read from msgbox child process failed");
|
||||
*buttonid = 0;
|
||||
}
|
||||
|
||||
if (read(fds[0], &status, sizeof (int)) != sizeof (int))
|
||||
status = -1;
|
||||
else if (read(fds[0], buttonid, sizeof (int)) != sizeof (int))
|
||||
status = -1;
|
||||
close(fds[0]);
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -1011,7 +1011,13 @@ static int (*PreXRRSetScreenSizeErrorHandler)(Display *, XErrorEvent *) = NULL;
|
|||
static int
|
||||
SDL_XRRSetScreenSizeErrHandler(Display *d, XErrorEvent *e)
|
||||
{
|
||||
return (e->error_code == BadMatch) ? 0 : PreXRRSetScreenSizeErrorHandler(d, e);
|
||||
/* BadMatch: https://github.com/libsdl-org/SDL/issues/4561 */
|
||||
/* BadValue: https://github.com/libsdl-org/SDL/issues/4840 */
|
||||
if ((e->error_code == BadMatch) || (e->error_code == BadValue)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PreXRRSetScreenSizeErrorHandler(d, e);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -247,11 +247,6 @@ X11_GL_LoadLibrary(_THIS, const char *path)
|
|||
X11_GL_UseEGL(_this) ) {
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
X11_GL_UnloadLibrary(_this);
|
||||
/* Better avoid conflicts! */
|
||||
if (_this->gl_config.dll_handle != NULL ) {
|
||||
GL_UnloadObject(_this->gl_config.dll_handle);
|
||||
_this->gl_config.dll_handle = NULL;
|
||||
}
|
||||
_this->GL_LoadLibrary = X11_GLES_LoadLibrary;
|
||||
_this->GL_GetProcAddress = X11_GLES_GetProcAddress;
|
||||
_this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,6 @@ SDL_X11_SYM(XkbDescPtr,XkbGetMap,(Display* a,unsigned int b,unsigned int c),(a,b
|
|||
SDL_X11_SYM(void,XkbFreeClientMap,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
|
||||
SDL_X11_SYM(void,XkbFreeKeyboard,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
|
||||
SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c),return)
|
||||
SDL_X11_SYM(Bool,XkbSelectEvents,(Display* a, unsigned int b, unsigned int c, unsigned int d),(a,b,c,d),return)
|
||||
#endif
|
||||
|
||||
#if NeedWidePrototypes
|
||||
|
|
|
|||
|
|
@ -678,8 +678,6 @@ X11_CreateWindow(_THIS, SDL_Window * window)
|
|||
/* For _ICC_PROFILE. */
|
||||
X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask);
|
||||
|
||||
X11_XkbSelectEvents(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
|
||||
|
||||
X11_XFlush(display);
|
||||
|
||||
return 0;
|
||||
|
|
@ -782,11 +780,22 @@ X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
|
|||
X11_XFlush(display);
|
||||
}
|
||||
|
||||
static SDL_bool caught_x11_error = SDL_FALSE;
|
||||
static int
|
||||
X11_CatchAnyError(Display * d, XErrorEvent * e)
|
||||
{
|
||||
/* this may happen during tumultuous times when we are polling anyhow,
|
||||
so just note we had an error and return control. */
|
||||
caught_x11_error = SDL_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
X11_SetWindowPosition(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
Display *display = data->videodata->display;
|
||||
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
|
||||
unsigned int childCount;
|
||||
Window childReturn, root, parent;
|
||||
Window* children;
|
||||
|
|
@ -805,20 +814,27 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
|
|||
|
||||
/* Wait a brief time to see if the window manager decided to let this move happen.
|
||||
If the window changes at all, even to an unexpected value, we break out. */
|
||||
X11_XSync(display, False);
|
||||
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||
|
||||
timeout = SDL_GetTicks() + 100;
|
||||
while (SDL_TRUE) {
|
||||
int x, y;
|
||||
|
||||
caught_x11_error = SDL_FALSE;
|
||||
X11_XSync(display, False);
|
||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
||||
attrs.x, attrs.y, &x, &y, &childReturn);
|
||||
|
||||
if ((x != orig_x) || (y != orig_y)) {
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
break; /* window moved, time to go. */
|
||||
} else if ((x == window->x) && (y == window->y)) {
|
||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||
if (!caught_x11_error) {
|
||||
if ((x != orig_x) || (y != orig_y)) {
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
break; /* window moved, time to go. */
|
||||
} else if ((x == window->x) && (y == window->y)) {
|
||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
||||
|
|
@ -827,6 +843,9 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
|
|||
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
X11_XSetErrorHandler(prev_handler);
|
||||
caught_x11_error = SDL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -892,6 +911,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
|||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
Display *display = data->videodata->display;
|
||||
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
|
||||
XWindowAttributes attrs;
|
||||
int orig_w, orig_h;
|
||||
Uint32 timeout;
|
||||
|
|
@ -943,19 +963,25 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
|||
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
|
||||
}
|
||||
|
||||
X11_XSync(display, False);
|
||||
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||
|
||||
/* Wait a brief time to see if the window manager decided to let this resize happen.
|
||||
If the window changes at all, even to an unexpected value, we break out. */
|
||||
timeout = SDL_GetTicks() + 100;
|
||||
while (SDL_TRUE) {
|
||||
caught_x11_error = SDL_FALSE;
|
||||
X11_XSync(display, False);
|
||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||
|
||||
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
|
||||
window->w = attrs.width;
|
||||
window->h = attrs.height;
|
||||
break; /* window changed, time to go. */
|
||||
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
|
||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||
if (!caught_x11_error) {
|
||||
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
|
||||
window->w = attrs.width;
|
||||
window->h = attrs.height;
|
||||
break; /* window changed, time to go. */
|
||||
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
|
||||
break; /* we're at the place we wanted to be anyhow, drop out. */
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
|
||||
|
|
@ -964,6 +990,9 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
|
|||
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
X11_XSetErrorHandler(prev_handler);
|
||||
caught_x11_error = SDL_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1281,6 +1310,22 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
|
|||
|
||||
if (X11_IsWindowMapped(_this, window)) {
|
||||
XEvent e;
|
||||
/* !!! FIXME: most of this waiting code is copy/pasted from elsewhere. */
|
||||
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
|
||||
unsigned int childCount;
|
||||
Window childReturn, root, parent;
|
||||
Window* children;
|
||||
XWindowAttributes attrs;
|
||||
int orig_w, orig_h, orig_x, orig_y;
|
||||
Uint64 timeout;
|
||||
|
||||
X11_XSync(display, False);
|
||||
X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
|
||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
||||
attrs.x, attrs.y, &orig_x, &orig_y, &childReturn);
|
||||
orig_w = attrs.width;
|
||||
orig_h = attrs.height;
|
||||
|
||||
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
|
||||
/* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
|
||||
|
|
@ -1330,6 +1375,41 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
|
|||
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
|
||||
SubstructureNotifyMask | SubstructureRedirectMask, &e);
|
||||
}
|
||||
|
||||
/* Wait a brief time to see if the window manager decided to let this happen.
|
||||
If the window changes at all, even to an unexpected value, we break out. */
|
||||
X11_XSync(display, False);
|
||||
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
|
||||
|
||||
timeout = SDL_GetTicks64() + 100;
|
||||
while (SDL_TRUE) {
|
||||
int x, y;
|
||||
|
||||
caught_x11_error = SDL_FALSE;
|
||||
X11_XSync(display, False);
|
||||
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
|
||||
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
|
||||
attrs.x, attrs.y, &x, &y, &childReturn);
|
||||
|
||||
if (!caught_x11_error) {
|
||||
if ((x != orig_x) || (y != orig_y) || (attrs.width != orig_w) || (attrs.height != orig_h)) {
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
window->w = attrs.width;
|
||||
window->h = attrs.height;
|
||||
break; /* window moved, time to go. */
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_GetTicks64() >= timeout) {
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
X11_XSetErrorHandler(prev_handler);
|
||||
caught_x11_error = SDL_FALSE;
|
||||
} else {
|
||||
Uint32 flags;
|
||||
|
||||
|
|
|
|||
|
|
@ -426,9 +426,17 @@ void SSE_FUNCTION_NAME(uint32_t width, uint32_t height,
|
|||
const int fix_read_nv12 = 0;
|
||||
#endif
|
||||
|
||||
#if YUV_FORMAT == YUV_FORMAT_422
|
||||
/* Avoid invalid read on last line */
|
||||
const int fix_read_422 = 1;
|
||||
#else
|
||||
const int fix_read_422 = 0;
|
||||
#endif
|
||||
|
||||
|
||||
if (width >= 32) {
|
||||
uint32_t xpos, ypos;
|
||||
for(ypos=0; ypos<(height-(uv_y_sample_interval-1)); ypos+=uv_y_sample_interval)
|
||||
for(ypos=0; ypos<(height-(uv_y_sample_interval-1)) - fix_read_422; ypos+=uv_y_sample_interval)
|
||||
{
|
||||
const uint8_t *y_ptr1=Y+ypos*Y_stride,
|
||||
*y_ptr2=Y+(ypos+1)*Y_stride,
|
||||
|
|
@ -459,6 +467,15 @@ void SSE_FUNCTION_NAME(uint32_t width, uint32_t height,
|
|||
}
|
||||
}
|
||||
|
||||
if (fix_read_422) {
|
||||
const uint8_t *y_ptr=Y+ypos*Y_stride,
|
||||
*u_ptr=U+(ypos/uv_y_sample_interval)*UV_stride,
|
||||
*v_ptr=V+(ypos/uv_y_sample_interval)*UV_stride;
|
||||
uint8_t *rgb_ptr=RGB+ypos*RGB_stride;
|
||||
STD_FUNCTION_NAME(width, 1, y_ptr, u_ptr, v_ptr, Y_stride, UV_stride, rgb_ptr, RGB_stride, yuv_type);
|
||||
ypos += uv_y_sample_interval;
|
||||
}
|
||||
|
||||
/* Catch the last line, if needed */
|
||||
if (uv_y_sample_interval == 2 && ypos == (height-1))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue