early-access version 1988

This commit is contained in:
pineappleEA
2021-08-12 01:07:27 +02:00
parent e37f82ce96
commit 24ddfcbb39
265 changed files with 68343 additions and 5348 deletions

View File

@@ -34,7 +34,7 @@ SDL_memcpySSE(Uint8 * dst, const Uint8 * src, int len)
__m128 values[4];
for (i = len / 64; i--;) {
_mm_prefetch(src, _MM_HINT_NTA);
_mm_prefetch((const char *)src, _MM_HINT_NTA);
values[0] = *(__m128 *) (src + 0);
values[1] = *(__m128 *) (src + 16);
values[2] = *(__m128 *) (src + 32);

View File

@@ -411,9 +411,9 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
biClrUsed = 1 << biBitCount;
}
if (biClrUsed > palette->ncolors) {
if (biClrUsed > (Uint32)palette->ncolors) {
biClrUsed = 1 << biBitCount; /* try forcing it? */
if (biClrUsed > palette->ncolors) {
if (biClrUsed > (Uint32)palette->ncolors) {
SDL_SetError("Unsupported or incorrect biClrUsed field");
was_error = SDL_TRUE;
goto done;

View File

@@ -507,12 +507,12 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
}
if (_this->egl_data->eglGetPlatformDisplay) {
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(size_t)native_display, NULL);
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, NULL);
} else {
if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
_this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
if (_this->egl_data->eglGetPlatformDisplayEXT) {
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(size_t)native_display, NULL);
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(uintptr_t)native_display, NULL);
}
}
}

View File

@@ -240,7 +240,7 @@ struct SDL_VideoDevice
int (*UpdateWindowFramebuffer) (_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
void (*DestroyWindowFramebuffer) (_THIS, SDL_Window * window);
void (*OnWindowEnter) (_THIS, SDL_Window * window);
int (*FlashWindow) (_THIS, SDL_Window * window, Uint32 flash_count);
int (*FlashWindow) (_THIS, SDL_Window * window, SDL_FlashOperation operation);
/* * * */
/*

View File

@@ -492,17 +492,27 @@ SDL_VideoInit(const char *driver_name)
}
/* Select the proper video driver */
index = 0;
i = index = 0;
video = NULL;
if (driver_name == NULL) {
driver_name = SDL_getenv("SDL_VIDEODRIVER");
}
if (driver_name != NULL) {
for (i = 0; bootstrap[i]; ++i) {
if (SDL_strncasecmp(bootstrap[i]->name, driver_name, SDL_strlen(driver_name)) == 0) {
video = bootstrap[i]->create(index);
break;
const char *driver_attempt = driver_name;
while(driver_attempt != NULL && *driver_attempt != 0 && video == NULL) {
const char* driver_attempt_end = SDL_strchr(driver_attempt, ',');
size_t driver_attempt_len = (driver_attempt_end != NULL) ? (driver_attempt_end - driver_attempt)
: SDL_strlen(driver_attempt);
for (i = 0; bootstrap[i]; ++i) {
if ((driver_attempt_len == SDL_strlen(bootstrap[i]->name)) &&
(SDL_strncasecmp(bootstrap[i]->name, driver_attempt, driver_attempt_len) == 0)) {
video = bootstrap[i]->create(index);
break;
}
}
driver_attempt = (driver_attempt_end != NULL) ? (driver_attempt_end + 1) : NULL;
}
} else {
for (i = 0; bootstrap[i]; ++i) {
@@ -1153,7 +1163,16 @@ SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode)
if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
SDL_DisplayMode fullscreen_mode;
if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
SDL_SetDisplayModeForDisplay(SDL_GetDisplayForWindow(window), &fullscreen_mode);
if (SDL_SetDisplayModeForDisplay(SDL_GetDisplayForWindow(window), &fullscreen_mode) == 0) {
#ifndef ANDROID
/* Android may not resize the window to exactly what our fullscreen mode is, especially on
* windowed Android environments like the Chromebook or Samsung DeX. Given this, we shouldn't
* use fullscreen_mode.w and fullscreen_mode.h, but rather get our current native size. As such,
* Android's SetWindowFullscreen will generate the window event for us with the proper final size.
*/
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, fullscreen_mode.w, fullscreen_mode.h);
#endif
}
}
}
return 0;
@@ -1349,11 +1368,11 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
/* Generate a mode change event here */
if (resized) {
#ifndef ANDROID
// Android may not resize the window to exactly what our fullscreen mode is, especially on
// windowed Android environments like the Chromebook or Samsung DeX. Given this, we shouldn't
// use fullscreen_mode.w and fullscreen_mode.h, but rather get our current native size. As such,
// Android's SetWindowFullscreen will generate the window event for us with the proper final size.
/* Android may not resize the window to exactly what our fullscreen mode is, especially on
* windowed Android environments like the Chromebook or Samsung DeX. Given this, we shouldn't
* use fullscreen_mode.w and fullscreen_mode.h, but rather get our current native size. As such,
* Android's SetWindowFullscreen will generate the window event for us with the proper final size.
*/
SDL_SendWindowEvent(other, SDL_WINDOWEVENT_RESIZED,
fullscreen_mode.w, fullscreen_mode.h);
#endif
@@ -1589,6 +1608,22 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
displayIndex = SDL_GetIndexOfDisplay(display);
SDL_GetDisplayBounds(displayIndex, &bounds);
/* for real fullscreen we might switch the resolution, so get width and height
* from closest supported mode and use that instead of current resolution
*/
if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP
&& (bounds.w != w || bounds.h != h)) {
SDL_DisplayMode fullscreen_mode, closest_mode;
SDL_zero(fullscreen_mode);
fullscreen_mode.w = w;
fullscreen_mode.h = h;
if (SDL_GetClosestDisplayModeForDisplay(display, &fullscreen_mode, &closest_mode) != NULL) {
bounds.w = closest_mode.w;
bounds.h = closest_mode.h;
}
}
window->fullscreen_mode.w = bounds.w;
window->fullscreen_mode.h = bounds.h;
window->x = bounds.x;
window->y = bounds.y;
window->w = bounds.w;
@@ -2793,12 +2828,12 @@ SDL_GetGrabbedWindow(void)
}
int
SDL_FlashWindow(SDL_Window * window, Uint32 flash_count)
SDL_FlashWindow(SDL_Window * window, SDL_FlashOperation operation)
{
CHECK_WINDOW_MAGIC(window, -1);
if (_this->FlashWindow) {
return _this->FlashWindow(_this, window, flash_count);
return _this->FlashWindow(_this, window, operation);
}
return SDL_Unsupported();
@@ -2820,7 +2855,10 @@ void
SDL_OnWindowResized(SDL_Window * window)
{
window->surface_valid = SDL_FALSE;
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
if (!window->is_destroying) {
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
}
}
void
@@ -2878,6 +2916,8 @@ SDL_OnWindowFocusGained(SDL_Window * window)
static SDL_bool
ShouldMinimizeOnFocusLoss(SDL_Window * window)
{
const char *hint;
if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
return SDL_FALSE;
}
@@ -2893,12 +2933,21 @@ ShouldMinimizeOnFocusLoss(SDL_Window * window)
#ifdef __ANDROID__
{
extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void);
if (! Android_JNI_ShouldMinimizeOnFocusLoss()) {
if (!Android_JNI_ShouldMinimizeOnFocusLoss()) {
return SDL_FALSE;
}
}
#endif
/* 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) {
return SDL_FALSE;
} else {
return SDL_TRUE;
}
}
return SDL_GetHintBoolean(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_FALSE);
}

View File

@@ -31,6 +31,8 @@ extern void Cocoa_StartTextInput(_THIS);
extern void Cocoa_StopTextInput(_THIS);
extern void Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect);
extern void Cocoa_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
#endif /* SDL_cocoakeyboard_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -602,6 +602,23 @@ Cocoa_QuitKeyboard(_THIS)
{
}
typedef int CGSConnection;
typedef enum {
CGSGlobalHotKeyEnable = 0,
CGSGlobalHotKeyDisable = 1,
} CGSGlobalHotKeyOperatingMode;
extern CGSConnection _CGSDefaultConnection(void);
extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, CGSGlobalHotKeyOperatingMode mode);
void
Cocoa_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
#if SDL_MAC_NO_SANDBOX
CGSSetGlobalHotKeyOperatingMode(_CGSDefaultConnection(), grabbed ? CGSGlobalHotKeyDisable : CGSGlobalHotKeyEnable);
#endif
}
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -89,10 +89,8 @@
@end
/* Display a Cocoa message box */
int
Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{ @autoreleasepool
static void
Cocoa_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
{
Cocoa_RegisterApp();
@@ -133,11 +131,8 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
SDLMessageBoxPresenter* presenter = [[[SDLMessageBoxPresenter alloc] initWithParentWindow:messageboxdata->window] autorelease];
[presenter performSelectorOnMainThread:@selector(showAlert:)
withObject:alert
waitUntilDone:YES];
[presenter showAlert:alert];
int returnValue = 0;
NSInteger clicked = presenter->clicked;
if (clicked >= NSAlertFirstButtonReturn) {
clicked -= NSAlertFirstButtonReturn;
@@ -145,10 +140,24 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
clicked = messageboxdata->numbuttons - 1 - clicked;
}
*buttonid = buttons[clicked].buttonid;
*returnValue = 0;
} else {
returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
*returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
}
}
/* Display a Cocoa message box */
int
Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{ @autoreleasepool
{
__block int returnValue = 0;
if ([NSThread isMainThread]) {
Cocoa_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue);
} else {
dispatch_sync(dispatch_get_main_queue(), ^{ Cocoa_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue); });
}
return returnValue;
}}

View File

@@ -215,8 +215,8 @@ Cocoa_WarpMouseGlobal(int x, int y)
SDL_Mouse *mouse = SDL_GetMouse();
if (mouse->focus) {
SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
if ([data->listener isMoving]) {
DLog("Postponing warp, window being moved.");
if ([data->listener isMovingOrFocusClickPending]) {
DLog("Postponing warp, window being moved or focused.");
[data->listener setPendingMoveX:x Y:y];
return 0;
}
@@ -271,7 +271,7 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
* if it is being moved right now.
*/
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if ([data->listener isMoving]) {
if ([data->listener isMovingOrFocusClickPending]) {
return 0;
}
@@ -353,6 +353,34 @@ Cocoa_InitMouse(_THIS)
return 0;
}
static void
Cocoa_HandleTitleButtonEvent(_THIS, NSEvent *event)
{
SDL_Window *window;
NSWindow *nswindow = [event window];
for (window = _this->windows; window; window = window->next) {
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
if (data && data->nswindow == nswindow) {
switch ([event type]) {
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
[data->listener setFocusClickPending:[event buttonNumber]];
break;
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
[data->listener clearFocusClickPending:[event buttonNumber]];
break;
default:
break;
}
break;
}
}
}
void
Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
{
@@ -363,6 +391,21 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
case NSEventTypeOtherMouseDragged:
break;
case NSEventTypeLeftMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseDown:
case NSEventTypeOtherMouseUp:
if ([event window]) {
NSRect windowRect = [[[event window] contentView] frame];
if (!NSMouseInRect([event locationInWindow], windowRect, NO)) {
Cocoa_HandleTitleButtonEvent(_this, event);
return;
}
}
return;
default:
/* Ignore any other events. */
return;

View File

@@ -103,10 +103,12 @@ Cocoa_CreateDevice(int devindex)
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab;
device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab;
device->DestroyWindow = Cocoa_DestroyWindow;
device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
device->SetWindowHitTest = Cocoa_SetWindowHitTest;
device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop;
device->FlashWindow = Cocoa_FlashWindow;
device->shape_driver.CreateShaper = Cocoa_CreateShaper;
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;

View File

@@ -48,6 +48,7 @@ typedef enum
BOOL inFullscreenTransition;
PendingWindowOperation pendingWindowOperation;
BOOL isMoving;
int focusClickPending;
int pendingWindowWarpX, pendingWindowWarpY;
BOOL isDragAreaRunning;
}
@@ -62,8 +63,12 @@ typedef enum
-(void) close;
-(BOOL) isMoving;
-(BOOL) isMovingOrFocusClickPending;
-(void) setFocusClickPending:(int) button;
-(void) clearFocusClickPending:(int) button;
-(void) setPendingMoveX:(int)x Y:(int)y;
-(void) windowDidFinishMoving;
-(void) onMovingOrFocusClickPendingStateCleared;
/* Window delegate functionality */
-(BOOL) windowShouldClose:(id) sender;
@@ -117,6 +122,7 @@ struct SDL_WindowData
NSMutableArray *nscontexts;
SDL_bool created;
SDL_bool inWindowFullscreenTransition;
NSInteger flash_request;
Cocoa_WindowListener *listener;
struct SDL_VideoData *videodata;
#if SDL_VIDEO_OPENGL_EGL
@@ -151,6 +157,7 @@ extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void Cocoa_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int Cocoa_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation);
#endif /* SDL_cocoawindow_h_ */

View File

@@ -508,6 +508,26 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
return isMoving;
}
- (BOOL)isMovingOrFocusClickPending
{
return isMoving || (focusClickPending != 0);
}
-(void) setFocusClickPending:(int) button
{
focusClickPending |= (1 << button);
}
-(void) clearFocusClickPending:(int) button
{
if ((focusClickPending & (1 << button)) != 0) {
focusClickPending &= ~(1 << button);
if (focusClickPending == 0) {
[self onMovingOrFocusClickPendingStateCleared];
}
}
}
-(void) setPendingMoveX:(int)x Y:(int)y
{
pendingWindowWarpX = x;
@@ -516,15 +536,36 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
- (void)windowDidFinishMoving
{
if ([self isMoving]) {
if (isMoving) {
isMoving = NO;
[self onMovingOrFocusClickPendingStateCleared];
}
}
- (void)onMovingOrFocusClickPendingStateCleared
{
if (![self isMovingOrFocusClickPending]) {
SDL_Mouse *mouse = SDL_GetMouse();
if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
mouse->WarpMouseGlobal(pendingWindowWarpX, pendingWindowWarpY);
pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
}
if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data->window) {
/* Move the cursor to the nearest point in the window */
{
int x, y;
CGPoint cgpoint;
SDL_GetMouseState(&x, &y);
cgpoint.x = _data->window->x + x;
cgpoint.y = _data->window->y + y;
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
}
mouse->SetRelativeMouseMode(SDL_TRUE);
}
}
@@ -641,7 +682,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
/* This needs to be done before restoring the relative mouse mode. */
SDL_SetKeyboardFocus(window);
if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMoving]) {
if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMovingOrFocusClickPending]) {
mouse->SetRelativeMouseMode(SDL_TRUE);
}
@@ -1970,7 +2011,7 @@ Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
/* Move the cursor to the nearest point in the window */
if (grabbed && data && ![data->listener isMoving]) {
if (grabbed && data && ![data->listener isMovingOrFocusClickPending]) {
int x, y;
CGPoint cgpoint;
@@ -2116,6 +2157,34 @@ Cocoa_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
}
}
int
Cocoa_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)
{ @autoreleasepool
{
/* Note that this is app-wide and not window-specific! */
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data->flash_request) {
[NSApp cancelUserAttentionRequest:data->flash_request];
data->flash_request = 0;
}
switch (operation) {
case SDL_FLASH_CANCEL:
/* Canceled above */
break;
case SDL_FLASH_BRIEFLY:
data->flash_request = [NSApp requestUserAttention:NSInformationalRequest];
break;
case SDL_FLASH_UNTIL_FOCUSED:
data->flash_request = [NSApp requestUserAttention:NSCriticalRequest];
break;
default:
return SDL_Unsupported();
}
return 0;
}}
int
Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
{

View File

@@ -116,6 +116,7 @@ DUMMY_VideoInit(_THIS)
SDL_DisplayMode mode;
/* Use a fake 32-bpp desktop mode */
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGB888;
mode.w = 1024;
mode.h = 768;
@@ -125,7 +126,6 @@ DUMMY_VideoInit(_THIS)
return -1;
}
SDL_zero(mode);
SDL_AddDisplayMode(&_this->displays[0], &mode);
/* We're done! */

View File

@@ -290,6 +290,7 @@ KMSDRM_CreateDevice(int devindex)
device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
device->GL_DefaultProfileConfig = KMSDRM_GLES_DefaultProfileConfig;
#if SDL_VIDEO_VULKAN
device->Vulkan_LoadLibrary = KMSDRM_Vulkan_LoadLibrary;
@@ -537,8 +538,10 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_DisplayData *dispdata = NULL;
SDL_VideoDisplay display = {0};
SDL_DisplayModeData *modedata = NULL;
drmModeEncoder *encoder = NULL;
drmModeCrtc *crtc = NULL;
int mode_index;
int i, j;
int ret = 0;
@@ -626,6 +629,23 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
goto cleanup;
}
/* Find the index of the mode attached to this CRTC */
mode_index = -1;
for (i = 0; i < connector->count_modes; i++) {
drmModeModeInfo *mode = &connector->modes[i];
if (!SDL_memcmp(mode, &crtc->mode, sizeof(crtc->mode))) {
mode_index = i;
break;
}
}
if (mode_index == -1) {
ret = SDL_SetError("Failed to find index of mode attached to the CRTC.");
goto cleanup;
}
/*********************************************/
/* Create an SDL Display for this connector. */
/*********************************************/
@@ -638,9 +658,8 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
which is the mode currently setup on the CRTC
we found for the active connector. */
dispdata->mode = crtc->mode;
/* Save the original mode for restoration on quit. */
dispdata->original_mode = dispdata->mode;
dispdata->original_mode = crtc->mode;
dispdata->fullscreen_mode = crtc->mode;
if (dispdata->mode.hdisplay == 0 || dispdata->mode.vdisplay == 0 ) {
ret = SDL_SetError("Couldn't get a valid connector videomode.");
@@ -657,11 +676,21 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
/* Setup the display.
There's no problem with it being still incomplete. */
modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData));
if (!modedata) {
ret = SDL_OutOfMemory();
goto cleanup;
}
modedata->mode_index = mode_index;
display.driverdata = dispdata;
display.desktop_mode.w = dispdata->mode.hdisplay;
display.desktop_mode.h = dispdata->mode.vdisplay;
display.desktop_mode.refresh_rate = dispdata->mode.vrefresh;
display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888;
display.desktop_mode.driverdata = modedata;
display.current_mode = display.desktop_mode;
/* Add the display to the list of SDL displays. */
@@ -899,6 +928,43 @@ KMSDRM_DestroySurfaces(_THIS, SDL_Window *window)
}
}
static void
KMSDRM_GetModeToSet(SDL_Window *window, drmModeModeInfo *out_mode) {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = (SDL_DisplayData *)display->driverdata;
if ((window->flags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN) {
*out_mode = dispdata->fullscreen_mode;
} else {
drmModeModeInfo *mode;
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, 0);
if (mode) {
*out_mode = *mode;
} else {
*out_mode = dispdata->original_mode;
}
}
}
static void
KMSDRM_DirtySurfaces(SDL_Window *window) {
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
drmModeModeInfo mode;
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow
so the correct thread-local surface and context state are available */
windata->egl_surface_dirty = SDL_TRUE;
/* The app may be waiting for the resize event after calling SetWindowSize
or SetWindowFullscreen, send a fake event for now since the actual
recreation is deferred */
KMSDRM_GetModeToSet(window, &mode);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.hdisplay, mode.vdisplay);
}
/* This determines the size of the fb, which comes from the GBM surface
that we create here. */
int
@@ -906,7 +972,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayForWindow(window)->driverdata;
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = (SDL_DisplayData *)display->driverdata;
uint32_t surface_fmt = GBM_FORMAT_ARGB8888;
uint32_t surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
@@ -915,9 +982,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
int ret = 0;
/* If the current window already has surfaces, destroy them before creating other.
This is mainly for ReconfigureWindow(), where we simply call CreateSurfaces()
for regenerating a window's surfaces. */
/* If the current window already has surfaces, destroy them before creating other. */
if (windata->gs) {
KMSDRM_DestroySurfaces(_this, window);
}
@@ -928,6 +993,16 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
"GBM surface format not supported. Trying anyway.");
}
/* The KMSDRM backend doesn't always set the mode the higher-level code in
SDL_video.c expects. Hulk-smash the display's current_mode to keep the
mode that's set in sync with what SDL_video.c thinks is set */
KMSDRM_GetModeToSet(window, &dispdata->mode);
display->current_mode.w = dispdata->mode.hdisplay;
display->current_mode.h = dispdata->mode.vdisplay;
display->current_mode.refresh_rate = dispdata->mode.vrefresh;
display->current_mode.format = SDL_PIXELFORMAT_ARGB8888;
windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev,
dispdata->mode.hdisplay, dispdata->mode.vdisplay,
surface_fmt, surface_flags);
@@ -952,6 +1027,9 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
windata->egl_surface_dirty = SDL_FALSE;
cleanup:
@@ -1071,18 +1149,10 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
/* Take note of the new mode to be set, and leave the CRTC modeset pending
so it's done in SwapWindow. */
dispdata->mode = conn->modes[modedata->mode_index];
dispdata->fullscreen_mode = conn->modes[modedata->mode_index];
for (i = 0; i < viddata->num_windows; i++) {
SDL_Window *window = viddata->windows[i];
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow
so the correct thread-local surface and context state are available */
windata->egl_surface_dirty = SDL_TRUE;
/* Tell app about the window resize */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode->w, mode->h);
KMSDRM_DirtySurfaces(viddata->windows[i]);
}
return 0;
@@ -1244,14 +1314,13 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
are considered "windowed" at this point of their life.
If a window is fullscreen, SDL internals will call
KMSDRM_SetWindowFullscreen() to reconfigure it if necessary. */
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, 0 );
if (mode) {
dispdata->mode = *mode;
dispdata->fullscreen_mode = *mode;
} else {
dispdata->mode = dispdata->original_mode;
dispdata->fullscreen_mode = dispdata->original_mode;
}
/* Create the window surfaces with the size we have just chosen.
@@ -1259,12 +1328,6 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
if ((ret = KMSDRM_CreateSurfaces(_this, window))) {
return (SDL_SetError("Can't window GBM/EGL surfaces on window creation."));
}
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
} /* NON-Vulkan block ends. */
/* Add window to the internal list of tracked windows. Note, while it may
@@ -1300,56 +1363,6 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
return ret;
}
/*****************************************************************************/
/* Re-create a window surfaces without destroying the window itself, */
/* and set a videomode on the CRTC that matches the surfaces size. */
/* To be used by SetWindowSize() and SetWindowFullscreen(). */
/*****************************************************************************/
void
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window)
{
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = display->driverdata;
if ((window->flags & SDL_WINDOW_FULLSCREEN) ==
SDL_WINDOW_FULLSCREEN)
{
/* Nothing to do, honor the most recent mode requested by the user */
}
else if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) ==
SDL_WINDOW_FULLSCREEN_DESKTOP)
{
/* Update the current mode to the desktop mode. */
dispdata->mode = dispdata->original_mode;
} else {
drmModeModeInfo *mode;
/* Try to find a valid video mode matching the size of the window. */
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, 0);
if (mode) {
/* If matching mode found, recreate the GBM surface with the size
of that mode and configure it on the CRTC. */
dispdata->mode = *mode;
} else {
/* If not matching mode found, recreate the GBM surfaces with the
size of the mode that was originally configured on the CRTC,
and setup that mode on the CRTC. */
dispdata->mode = dispdata->original_mode;
}
}
/* Recreate the GBM (and EGL) surfaces, and mark the CRTC mode/fb setting
as pending so it's done on SwapWindow. */
KMSDRM_CreateSurfaces(_this, window);
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
}
int
KMSDRM_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
{
@@ -1409,7 +1422,7 @@ KMSDRM_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
if (!viddata->vulkan_mode) {
KMSDRM_ReconfigureWindow(_this, window);
KMSDRM_DirtySurfaces(window);
}
}
void
@@ -1418,7 +1431,7 @@ KMSDRM_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * displa
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
if (!viddata->vulkan_mode) {
KMSDRM_ReconfigureWindow(_this, window);
KMSDRM_DirtySurfaces(window);
}
}
void

View File

@@ -68,7 +68,7 @@ typedef struct SDL_DisplayData
drmModeCrtc *crtc;
drmModeModeInfo mode;
drmModeModeInfo original_mode;
drmModeModeInfo next_mode; /* New mode to be set on the CRTC. */
drmModeModeInfo fullscreen_mode;
drmModeCrtc *saved_crtc; /* CRTC to restore on quit */

View File

@@ -394,6 +394,8 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS,
/* SDL (and DRM, if we look at drmModeModeInfo vrefresh) uses plain integer Hz for
display mode refresh rate, but Vulkan expects higher precision. */
new_mode_parameters.refreshRate = window->fullscreen_mode.refresh_rate * 1000;
SDL_zero(display_mode_create_info);
display_mode_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR;
display_mode_create_info.parameters = new_mode_parameters;
result = vkCreateDisplayModeKHR(gpu,
@@ -419,11 +421,14 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS,
image_size.width = window->w;
image_size.height = window->h;
SDL_zero(display_plane_surface_create_info);
display_plane_surface_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR;
display_plane_surface_create_info.displayMode = display_mode;
/* For now, simply use the first plane. */
display_plane_surface_create_info.planeIndex = 0;
display_plane_surface_create_info.imageExtent = image_size;
display_plane_surface_create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
display_plane_surface_create_info.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
result = vkCreateDisplayPlaneSurfaceKHR(instance,
&display_plane_surface_create_info,
NULL,

View File

@@ -1562,8 +1562,14 @@ static int OS2_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi,
static void OS2_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
{
SDL_DisplayMode mode;
debug_os2("Enter");
SDL_AddDisplayMode(display, &display->current_mode);
SDL_memcpy(&mode, &display->current_mode, sizeof(SDL_DisplayMode));
mode.driverdata = (MODEDATA *) SDL_malloc(sizeof(MODEDATA));
if (!mode.driverdata) return; /* yikes.. */
SDL_memcpy(mode.driverdata, display->current_mode.driverdata, sizeof(MODEDATA));
SDL_AddDisplayMode(display, &mode);
}
static int OS2_SetDisplayMode(_THIS, SDL_VideoDisplay *display,

View File

@@ -31,6 +31,7 @@ extern void SDL_QuitGCKeyboard(void);
extern void SDL_InitGCMouse(void);
extern SDL_bool SDL_HasGCMouse(void);
extern SDL_bool SDL_GCMouseRelativeMode(void);
extern void SDL_QuitGCMouse(void);
#endif /* SDL_uikitevents_h_ */

View File

@@ -91,9 +91,9 @@ static void OnGCKeyboardConnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0
SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)keyCode);
};
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
keyboard.handlerQueue = queue;
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
keyboard.handlerQueue = queue;
}
static void OnGCKeyboardDisconnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
@@ -182,10 +182,22 @@ void SDL_QuitGCKeyboard(void)
static int mice_connected = 0;
static id mouse_connect_observer = nil;
static id mouse_disconnect_observer = nil;
static bool mouse_relative_mode = SDL_FALSE;
static void UpdateMouseGrab()
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window;
for (window = _this->windows; window != NULL; window = window->next) {
SDL_UpdateWindowGrab(window);
}
}
static int SetGCMouseRelativeMode(SDL_bool enabled)
{
/* We'll always send relative motion and we can't warp, so nothing to do here */
mouse_relative_mode = enabled;
UpdateMouseGrab();
return 0;
}
@@ -222,14 +234,16 @@ static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14
mouse.mouseInput.mouseMovedHandler = ^(GCMouseInput *mouse, float deltaX, float deltaY)
{
SDL_SendMouseMotion(SDL_GetMouseFocus(), mouseID, SDL_TRUE, (int)deltaX, -(int)deltaY);
SDL_SendMouseMotion(SDL_GetMouseFocus(), mouseID, SDL_TRUE, (int)deltaX, -(int)deltaY);
};
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
mouse.handlerQueue = queue;
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
mouse.handlerQueue = queue;
++mice_connected;
UpdateMouseGrab();
}
static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
@@ -245,12 +259,14 @@ static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios
for (GCControllerButtonInput *button in mouse.mouseInput.auxiliaryButtons) {
button.pressedChangedHandler = nil;
}
UpdateMouseGrab();
}
void SDL_InitGCMouse(void)
{
@autoreleasepool {
/* There is a bug where mouse accumulates duplicate deltas over time in iOS 14.0 */
@autoreleasepool {
/* There is a bug where mouse accumulates duplicate deltas over time in iOS 14.0 */
if (@available(iOS 14.1, tvOS 14.1, *)) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
@@ -284,6 +300,11 @@ SDL_bool SDL_HasGCMouse(void)
return (mice_connected > 0);
}
SDL_bool SDL_GCMouseRelativeMode(void)
{
return mouse_relative_mode;
}
void SDL_QuitGCMouse(void)
{
@autoreleasepool {
@@ -320,6 +341,11 @@ SDL_bool SDL_HasGCMouse(void)
return SDL_FALSE;
}
SDL_bool SDL_GCMouseRelativeMode(void)
{
return SDL_FALSE;
}
void SDL_QuitGCMouse(void)
{
}

View File

@@ -93,6 +93,7 @@ UIKit_CreateDevice(int devindex)
device->RaiseWindow = UIKit_RaiseWindow;
device->SetWindowBordered = UIKit_SetWindowBordered;
device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
device->SetWindowMouseGrab = UIKit_SetWindowMouseGrab;
device->DestroyWindow = UIKit_DestroyWindow;
device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
@@ -159,8 +160,8 @@ UIKit_VideoInit(_THIS)
return -1;
}
SDL_InitGCKeyboard();
SDL_InitGCMouse();
SDL_InitGCKeyboard();
SDL_InitGCMouse();
return 0;
}
@@ -168,8 +169,8 @@ UIKit_VideoInit(_THIS)
void
UIKit_VideoQuit(_THIS)
{
SDL_QuitGCKeyboard();
SDL_QuitGCMouse();
SDL_QuitGCKeyboard();
SDL_QuitGCMouse();
UIKit_QuitModes(_this);
}

View File

@@ -27,8 +27,9 @@
#include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
#import "SDL_uikitviewcontroller.h"
#import "SDL_uikitmessagebox.h"
#include "SDL_uikitviewcontroller.h"
#include "SDL_uikitmessagebox.h"
#include "SDL_uikitevents.h"
#include "SDL_uikitvideo.h"
#include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h"
@@ -246,7 +247,20 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
return UIRectEdgeNone;
}
}
#endif
- (BOOL)prefersPointerLocked
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (SDL_HasGCMouse() &&
(SDL_GCMouseRelativeMode() || _this->grabbed_window == window)) {
return YES;
} else {
return NO;
}
}
#endif /* !TARGET_OS_TV */
/*
---- Keyboard related functionality below this line ----

View File

@@ -33,6 +33,7 @@ extern void UIKit_HideWindow(_THIS, SDL_Window * window);
extern void UIKit_RaiseWindow(_THIS, SDL_Window * window);
extern void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
extern void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern void UIKit_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo * info);

View File

@@ -161,14 +161,14 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
@autoreleasepool {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
SDL_Window *other;
SDL_Window *other;
/* We currently only handle a single window per display on iOS */
for (other = _this->windows; other; other = other->next) {
if (other != window && SDL_GetDisplayForWindow(other) == display) {
return SDL_SetError("Only one window allowed per display.");
}
}
for (other = _this->windows; other; other = other->next) {
if (other != window && SDL_GetDisplayForWindow(other) == display) {
return SDL_SetError("Only one window allowed per display.");
}
}
/* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
* user, so it's in standby), try to force the display to a resolution
@@ -320,6 +320,20 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
}
}
void
UIKit_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
#if !TARGET_OS_TV
@autoreleasepool {
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
if (@available(iOS 14.0, *)) {
[viewcontroller setNeedsUpdateOfPrefersPointerLocked];
}
}
#endif /* !TARGET_OS_TV */
}
void
UIKit_DestroyWindow(_THIS, SDL_Window * window)
{

View File

@@ -20,8 +20,7 @@
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_OPENGL_ES2
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PIB
#include <stdlib.h>
#include <string.h>
@@ -45,6 +44,23 @@
} \
} while (0)
void
VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
{
SceCommonDialogUpdateParam commonDialogParam;
SDL_zero(commonDialogParam);
commonDialogParam.renderTarget.colorFormat = data->colorFormat;
commonDialogParam.renderTarget.surfaceType = data->surfaceType;
commonDialogParam.renderTarget.colorSurfaceData = data->colorSurfaceData;
commonDialogParam.renderTarget.depthSurfaceData = data->depthSurfaceData;
commonDialogParam.renderTarget.width = data->width;
commonDialogParam.renderTarget.height = data->height;
commonDialogParam.renderTarget.strideInPixels = data->strideInPixels;
commonDialogParam.displaySyncObject = data->displaySyncObject;
sceCommonDialogUpdate(&commonDialogParam);
}
int
VITA_GL_LoadLibrary(_THIS, const char *path)
{
@@ -79,6 +95,7 @@ VITA_GL_CreateContext(_THIS, SDL_Window * window)
EGLSurface surface;
EGLConfig config;
EGLint num_configs;
PFNEGLPIGLETVITASETPRESWAPCALLBACKSCEPROC preSwapCallback;
int i;
const EGLint contextAttribs[] = {
@@ -141,6 +158,9 @@ VITA_GL_CreateContext(_THIS, SDL_Window * window)
_this->gl_data->context = context;
_this->gl_data->surface = surface;
preSwapCallback = (PFNEGLPIGLETVITASETPRESWAPCALLBACKSCEPROC) eglGetProcAddress("eglPigletVitaSetPreSwapCallbackSCE");
preSwapCallback(VITA_GL_KeyboardCallback);
return context;
}

View File

@@ -25,6 +25,7 @@
#include <pib.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

View File

@@ -33,11 +33,11 @@
int VITA_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
#if SDL_VIDEO_RENDER_VITA_GXM
SceCommonDialogConfigParam commonDialogConfigParam;
SceMsgDialogParam param;
SceMsgDialogUserMessageParam msgParam;
SceMsgDialogButtonsParam buttonParam;
SceDisplayFrameBuf dispparam;
char message[512];
SceMsgDialogResult dialog_result;
SceCommonDialogErrorCode init_result;
@@ -47,14 +47,17 @@ int VITA_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{
return -1;
}
SDL_zero(commonDialogConfigParam);
sceCommonDialogSetConfigParam(&commonDialogConfigParam);
SDL_zero(param);
sceMsgDialogParamInit(&param);
param.mode = SCE_MSG_DIALOG_MODE_USER_MSG;
SDL_zero(msgParam);
msgParam.msg = (const SceChar8*)messageboxdata->message;
SDL_snprintf(message, sizeof(message), "%s\r\n\r\n%s", messageboxdata->title, messageboxdata->message);
msgParam.msg = (const SceChar8*)message;
SDL_zero(buttonParam);
if (messageboxdata->numbuttons == 3)
{
msgParam.buttonType = SCE_MSG_DIALOG_BUTTON_TYPE_3BUTTONS;

View File

@@ -65,7 +65,7 @@ VITA_InitTouch(void)
// Support passing both front and back touch devices in events
SDL_AddTouch((SDL_TouchID)0, SDL_TOUCH_DEVICE_DIRECT, "Front");
SDL_AddTouch((SDL_TouchID)1, SDL_TOUCH_DEVICE_DIRECT, "Back");
SDL_AddTouch((SDL_TouchID)1, SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, "Back");
}
void

View File

@@ -38,7 +38,7 @@
#include "SDL_vitakeyboard.h"
#include "SDL_vitamouse_c.h"
#include "SDL_vitaframebuffer.h"
#if SDL_VIDEO_OPENGL_ES2
#if SDL_VIDEO_VITA_PIB
#include "SDL_vitagl_c.h"
#endif
#include <psp2/ime_dialog.h>
@@ -62,7 +62,7 @@ VITA_Create()
{
SDL_VideoDevice *device;
SDL_VideoData *phdata;
#if SDL_VIDEO_OPENGL_ES2
#if SDL_VIDEO_VITA_PIB
SDL_GLDriverData *gldata;
#endif
/* Initialize SDL_VideoDevice structure */
@@ -79,7 +79,7 @@ VITA_Create()
SDL_free(device);
return NULL;
}
#if SDL_VIDEO_OPENGL_ES2
#if SDL_VIDEO_VITA_PIB
gldata = (SDL_GLDriverData *) SDL_calloc(1, sizeof(SDL_GLDriverData));
if (gldata == NULL) {
@@ -130,7 +130,7 @@ VITA_Create()
device->DestroyWindowFramebuffer = VITA_DestroyWindowFramebuffer;
*/
#if SDL_VIDEO_OPENGL_ES2
#if SDL_VIDEO_VITA_PIB
device->GL_LoadLibrary = VITA_GL_LoadLibrary;
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
device->GL_UnloadLibrary = VITA_GL_UnloadLibrary;
@@ -418,6 +418,7 @@ void VITA_PumpEvents(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
VITA_PollTouch();
VITA_PollKeyboard();
VITA_PollMouse();
@@ -435,9 +436,13 @@ void VITA_PumpEvents(_THIS)
// Convert UTF16 to UTF8
utf16_to_utf8(videodata->ime_buffer, utf8_buffer);
// send sdl event
// Send SDL event
SDL_SendKeyboardText((const char*)utf8_buffer);
// Send enter key only on enter
if (result.button == SCE_IME_DIALOG_BUTTON_ENTER)
SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_RETURN);
sceImeDialogTerm();
videodata->ime_active = SDL_FALSE;
@@ -449,3 +454,4 @@ void VITA_PumpEvents(_THIS)
#endif /* SDL_VIDEO_DRIVER_VITA */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -34,8 +34,6 @@
#include "SDL_waylandvideo.h"
#include "SDL_waylanddatamanager.h"
#include "SDL_waylanddyn.h"
/* FIXME: This is arbitrary, but we want this to be less than a frame because
* any longer can potentially spin an infinite loop of PumpEvents (!)
*/
@@ -157,7 +155,7 @@ Wayland_convert_mime_type(const char *mime_type)
size_t index = 0;
for (index = 0; index < MIME_LIST_SIZE; ++index) {
if (strcmp(mime_conversion_list[index][0], mime_type) == 0) {
if (SDL_strcmp(mime_conversion_list[index][0], mime_type) == 0) {
found = mime_conversion_list[index][1];
break;
}
@@ -174,7 +172,7 @@ mime_data_list_find(struct wl_list* list,
SDL_MimeDataList *mime_list = NULL;
wl_list_for_each(mime_list, list, link) {
if (strcmp(mime_list->mime_type, mime_type) == 0) {
if (SDL_strcmp(mime_list->mime_type, mime_type) == 0) {
found = mime_list;
break;
}
@@ -426,7 +424,7 @@ Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device,
/* TODO - Improve system for multiple mime types to same data */
for (index = 0; index < MIME_LIST_SIZE; ++index) {
if (strcmp(mime_conversion_list[index][1], mime_data->mime_type) == 0) {
if (SDL_strcmp(mime_conversion_list[index][1], mime_data->mime_type) == 0) {
wl_data_source_offer(source->source,
mime_conversion_list[index][0]);
}

View File

@@ -47,12 +47,16 @@ typedef struct
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON NULL
#endif
#ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR
#define SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR NULL
#endif
static waylanddynlib waylandlibs[] = {
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON}
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON},
{NULL, SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR}
};
static void *

View File

@@ -18,13 +18,12 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_waylanddyn_h_
#define SDL_waylanddyn_h_
#include "../../SDL_internal.h"
/* We can't include wayland-client.h here
/* We can't include wayland-client.h here
* but we need some structs from it
*/
struct wl_interface;
@@ -34,6 +33,19 @@ struct wl_display;
struct wl_surface;
struct wl_shm;
/* We also need some for libdecor */
struct wl_seat;
struct wl_output;
struct libdecor;
struct libdecor_frame;
struct libdecor_state;
struct libdecor_configuration;
struct libdecor_interface;
struct libdecor_frame_interface;
enum libdecor_resize_edge;
enum libdecor_capabilities;
enum libdecor_window_state;
#include <stdint.h>
#include "wayland-cursor.h"
#include "wayland-util.h"
@@ -55,7 +67,6 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define SDL_WAYLAND_INTERFACE(iface) extern const struct wl_interface *WAYLAND_##iface;
#include "SDL_waylandsym.h"
#ifdef __cplusplus
}
#endif
@@ -82,25 +93,66 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_proxy_add_listener (*WAYLAND_wl_proxy_add_listener)
#define wl_proxy_marshal_constructor (*WAYLAND_wl_proxy_marshal_constructor)
#define wl_proxy_marshal_constructor_versioned (*WAYLAND_wl_proxy_marshal_constructor_versioned)
#define wl_proxy_set_tag (*WAYLAND_wl_proxy_set_tag)
#define wl_proxy_get_tag (*WAYLAND_wl_proxy_get_tag)
#define wl_seat_interface (*WAYLAND_wl_seat_interface)
#define wl_surface_interface (*WAYLAND_wl_surface_interface)
#define wl_shm_pool_interface (*WAYLAND_wl_shm_pool_interface)
#define wl_buffer_interface (*WAYLAND_wl_buffer_interface)
#define wl_registry_interface (*WAYLAND_wl_registry_interface)
#define wl_shell_surface_interface (*WAYLAND_wl_shell_surface_interface)
#define wl_region_interface (*WAYLAND_wl_region_interface)
#define wl_pointer_interface (*WAYLAND_wl_pointer_interface)
#define wl_keyboard_interface (*WAYLAND_wl_keyboard_interface)
#define wl_compositor_interface (*WAYLAND_wl_compositor_interface)
#define wl_output_interface (*WAYLAND_wl_output_interface)
#define wl_shell_interface (*WAYLAND_wl_shell_interface)
#define wl_shm_interface (*WAYLAND_wl_shm_interface)
#define wl_data_device_interface (*WAYLAND_wl_data_device_interface)
#define wl_data_offer_interface (*WAYLAND_wl_data_offer_interface)
#define wl_data_source_interface (*WAYLAND_wl_data_source_interface)
#define wl_data_device_manager_interface (*WAYLAND_wl_data_device_manager_interface)
#ifdef HAVE_LIBDECOR_H
/* Must be included before our defines */
#include <libdecor.h>
#define libdecor_unref (*WAYLAND_libdecor_unref)
#define libdecor_new (*WAYLAND_libdecor_new)
#define libdecor_decorate (*WAYLAND_libdecor_decorate)
#define libdecor_frame_unref (*WAYLAND_libdecor_frame_unref)
#define libdecor_frame_set_title (*WAYLAND_libdecor_frame_set_title)
#define libdecor_frame_set_app_id (*WAYLAND_libdecor_frame_set_app_id)
#define libdecor_frame_set_max_content_size (*WAYLAND_libdecor_frame_set_max_content_size)
#define libdecor_frame_set_min_content_size (*WAYLAND_libdecor_frame_set_min_content_size)
#define libdecor_frame_resize (*WAYLAND_libdecor_frame_resize)
#define libdecor_frame_move (*WAYLAND_libdecor_frame_move)
#define libdecor_frame_commit (*WAYLAND_libdecor_frame_commit)
#define libdecor_frame_set_minimized (*WAYLAND_libdecor_frame_set_minimized)
#define libdecor_frame_set_maximized (*WAYLAND_libdecor_frame_set_maximized)
#define libdecor_frame_unset_maximized (*WAYLAND_libdecor_frame_unset_maximized)
#define libdecor_frame_set_fullscreen (*WAYLAND_libdecor_frame_set_fullscreen)
#define libdecor_frame_unset_fullscreen (*WAYLAND_libdecor_frame_unset_fullscreen)
#define libdecor_frame_set_capabilities (*WAYLAND_libdecor_frame_set_capabilities)
#define libdecor_frame_unset_capabilities (*WAYLAND_libdecor_frame_unset_capabilities)
#define libdecor_frame_has_capability (*WAYLAND_libdecor_frame_has_capability)
#define libdecor_frame_set_visibility (*WAYLAND_libdecor_frame_set_visibility)
#define libdecor_frame_is_visible (*WAYLAND_libdecor_frame_is_visible)
#define libdecor_frame_is_floating (*WAYLAND_libdecor_frame_is_floating)
#define libdecor_frame_set_parent (*WAYLAND_libdecor_frame_set_parent)
#define libdecor_frame_get_xdg_surface (*WAYLAND_libdecor_frame_get_xdg_surface)
#define libdecor_frame_map (*WAYLAND_libdecor_frame_map)
#define libdecor_state_new (*WAYLAND_libdecor_state_new)
#define libdecor_state_free (*WAYLAND_libdecor_state_free)
#define libdecor_configuration_get_content_size (*WAYLAND_libdecor_configuration_get_content_size)
#define libdecor_configuration_get_window_state (*WAYLAND_libdecor_configuration_get_window_state)
#endif
#else /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
#endif
#endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */
#include "wayland-client-protocol.h"

View File

@@ -35,13 +35,15 @@
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylanddyn.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
#endif
#ifdef SDL_INPUT_LINUXEV
#include <linux/input.h>
@@ -195,14 +197,14 @@ keyboard_repeat_clear(SDL_WaylandKeyboardRepeat* repeat_info) {
static void
keyboard_repeat_set(SDL_WaylandKeyboardRepeat* repeat_info,
uint32_t scancode, SDL_bool has_text, char text[8]) {
if (!repeat_info->is_initialized) {
if (!repeat_info->is_initialized || !repeat_info->repeat_rate) {
return;
}
repeat_info->is_key_down = SDL_TRUE;
repeat_info->next_repeat_ms = SDL_GetTicks() + repeat_info->repeat_delay;
repeat_info->scancode = scancode;
if (has_text) {
memcpy(repeat_info->text, text, 8);
SDL_memcpy(repeat_info->text, text, 8);
} else {
repeat_info->text[0] = '\0';
}
@@ -218,7 +220,7 @@ Wayland_PumpEvents(_THIS)
WAYLAND_wl_display_flush(d->display);
#ifdef SDL_USE_IME
if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
if (d->text_input_manager == NULL && SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
SDL_IME_PumpEvents();
}
#endif
@@ -272,6 +274,11 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
return;
}
/* check that this surface belongs to one of the SDL windows */
if (!SDL_WAYLAND_own_surface(surface)) {
return;
}
/* This handler will be called twice in Wayland 1.4
* Once for the window surface which has valid user data
* and again for the mouse cursor surface which does not have valid user data
@@ -301,6 +308,10 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
{
struct SDL_WaylandInput *input = data;
if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return;
}
if (input->pointer_focus) {
SDL_SetMouseFocus(NULL);
input->pointer_focus = NULL;
@@ -317,35 +328,33 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
const SDL_Point point = { wl_fixed_to_int(input->sx_w), wl_fixed_to_int(input->sy_w) };
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
static const uint32_t directions_wl[] = {
WL_SHELL_SURFACE_RESIZE_TOP_LEFT, WL_SHELL_SURFACE_RESIZE_TOP,
WL_SHELL_SURFACE_RESIZE_TOP_RIGHT, WL_SHELL_SURFACE_RESIZE_RIGHT,
WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, WL_SHELL_SURFACE_RESIZE_BOTTOM,
WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT, WL_SHELL_SURFACE_RESIZE_LEFT
static const uint32_t directions[] = {
XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_TOP,
XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT, XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT, XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM,
XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT, XDG_TOPLEVEL_RESIZE_EDGE_LEFT
};
/* the names are different (ZXDG_TOPLEVEL_V6_RESIZE_EDGE_* vs
WL_SHELL_SURFACE_RESIZE_*), but the values are the same. */
const uint32_t *directions_zxdg = directions_wl;
#ifdef HAVE_LIBDECOR_H
/* ditto for libdecor. */
const uint32_t *directions_libdecor = directions;
#endif
switch (rc) {
case SDL_HITTEST_DRAGGABLE:
#ifdef HAVE_LIBDECOR_H
if (input->display->shell.libdecor) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_move(window_data->shell_surface.libdecor.frame, input->seat, serial);
}
} else
#endif
if (input->display->shell.xdg) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel,
input->seat,
serial);
}
} else if (input->display->shell.zxdg) {
if (window_data->shell_surface.zxdg.roleobj.toplevel) {
zxdg_toplevel_v6_move(window_data->shell_surface.zxdg.roleobj.toplevel,
input->seat,
serial);
}
} else {
if (window_data->shell_surface.wl) {
wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
}
}
return SDL_TRUE;
@@ -357,23 +366,19 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
case SDL_HITTEST_RESIZE_BOTTOM:
case SDL_HITTEST_RESIZE_BOTTOMLEFT:
case SDL_HITTEST_RESIZE_LEFT:
#ifdef HAVE_LIBDECOR_H
if (input->display->shell.libdecor) {
if (window_data->shell_surface.libdecor.frame) {
libdecor_frame_resize(window_data->shell_surface.libdecor.frame, input->seat, serial, directions_libdecor[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
} else
#endif
if (input->display->shell.xdg) {
if (window_data->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel,
input->seat,
serial,
directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
} else if (input->display->shell.zxdg) {
if (window_data->shell_surface.zxdg.roleobj.toplevel) {
zxdg_toplevel_v6_resize(window_data->shell_surface.zxdg.roleobj.toplevel,
input->seat,
serial,
directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
} else {
if (window_data->shell_surface.wl) {
wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions_wl[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
}
}
return SDL_TRUE;
@@ -528,7 +533,7 @@ pointer_handle_frame(void *data, struct wl_pointer *pointer)
y = input->pointer_curr_axis_info.y / WAYLAND_WHEEL_AXIS_UNIT;
/* clear pointer_curr_axis_info for next frame */
memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
SDL_memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
if(x == 0.0f && y == 0.0f)
return;
@@ -585,7 +590,7 @@ touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
touch_add(id, x, y, surface);
SDL_SendTouch(1, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
}
static void
@@ -603,7 +608,7 @@ touch_handler_up(void *data, struct wl_touch *touch, unsigned int serial,
window = window_data->sdlwindow;
}
SDL_SendTouch(1, (SDL_FingerID)id, window, SDL_FALSE, x, y, 0.0f);
SDL_SendTouch((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window, SDL_FALSE, x, y, 0.0f);
}
static void
@@ -617,7 +622,7 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
const float y = dbly / window_data->sdlwindow->h;
touch_update(id, x, y);
SDL_SendTouchMotion(1, (SDL_FingerID)id, window_data->sdlwindow, x, y, 1.0f);
SDL_SendTouchMotion((SDL_TouchID)(intptr_t)touch, (SDL_FingerID)id, window_data->sdlwindow, x, y, 1.0f);
}
static void
@@ -723,6 +728,10 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
return;
}
if (!SDL_WAYLAND_own_surface(surface)) {
return;
}
window = wl_surface_get_user_data(surface);
if (window) {
@@ -731,7 +740,9 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
SDL_SetKeyboardFocus(window->sdlwindow);
}
#ifdef SDL_USE_IME
SDL_IME_SetFocus(SDL_TRUE);
if (!input->text_input) {
SDL_IME_SetFocus(SDL_TRUE);
}
#endif
}
@@ -741,13 +752,20 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
{
struct SDL_WaylandInput *input = data;
if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return;
}
/* Stop key repeat before clearing keyboard focus */
keyboard_repeat_clear(&input->keyboard_repeat);
/* This will release any keys still pressed */
/* This will release any keys still pressed */
SDL_SetKeyboardFocus(NULL);
#ifdef SDL_USE_IME
SDL_IME_SetFocus(SDL_FALSE);
if (!input->text_input) {
SDL_IME_SetFocus(SDL_FALSE);
}
#endif
}
@@ -929,7 +947,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
input->pointer = wl_seat_get_pointer(seat);
memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
SDL_memset(&input->pointer_curr_axis_info, 0, sizeof input->pointer_curr_axis_info);
input->display->pointer = input->pointer;
wl_pointer_set_user_data(input->pointer, input);
wl_pointer_add_listener(input->pointer, &pointer_listener,
@@ -941,13 +959,13 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
}
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
SDL_AddTouch(1, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch");
input->touch = wl_seat_get_touch(seat);
SDL_AddTouch((SDL_TouchID)(intptr_t)input->touch, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch");
wl_touch_set_user_data(input->touch, input);
wl_touch_add_listener(input->touch, &touch_listener,
input);
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
SDL_DelTouch(1);
SDL_DelTouch((SDL_TouchID)(intptr_t)input->touch);
wl_touch_destroy(input->touch);
input->touch = NULL;
}
@@ -1210,6 +1228,93 @@ static const struct wl_data_device_listener data_device_listener = {
data_device_handle_selection
};
static void
text_input_enter(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
struct wl_surface *surface)
{
/* No-op */
}
static void
text_input_leave(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
struct wl_surface *surface)
{
/* No-op */
}
static void
text_input_preedit_string(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
const char *text,
int32_t cursor_begin,
int32_t cursor_end)
{
char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
if (text) {
size_t text_bytes = SDL_strlen(text), i = 0;
size_t cursor = 0;
do {
const size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
const size_t chars = SDL_utf8strlen(buf);
SDL_SendEditingText(buf, cursor, chars);
i += sz;
cursor += chars;
} while (i < text_bytes);
} else {
buf[0] = '\0';
SDL_SendEditingText(buf, 0, 0);
}
}
static void
text_input_commit_string(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
const char *text)
{
if (text && *text) {
char buf[SDL_TEXTINPUTEVENT_TEXT_SIZE];
size_t text_bytes = SDL_strlen(text), i = 0;
while (i < text_bytes) {
size_t sz = SDL_utf8strlcpy(buf, text+i, sizeof(buf));
SDL_SendKeyboardText(buf);
i += sz;
}
}
}
static void
text_input_delete_surrounding_text(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
uint32_t before_length,
uint32_t after_length)
{
/* FIXME: Do we care about this event? */
}
static void
text_input_done(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
uint32_t serial)
{
/* No-op */
}
static const struct zwp_text_input_v3_listener text_input_listener = {
text_input_enter,
text_input_leave,
text_input_preedit_string,
text_input_commit_string,
text_input_delete_surrounding_text,
text_input_done
};
static void
Wayland_create_data_device(SDL_VideoData *d)
{
@@ -1235,6 +1340,30 @@ Wayland_create_data_device(SDL_VideoData *d)
}
}
static void
Wayland_create_text_input(SDL_VideoData *d)
{
SDL_WaylandTextInput *text_input = NULL;
text_input = SDL_calloc(1, sizeof *text_input);
if (text_input == NULL) {
return;
}
text_input->text_input = zwp_text_input_manager_v3_get_text_input(
d->text_input_manager, d->input->seat
);
if (text_input->text_input == NULL) {
SDL_free(text_input);
} else {
zwp_text_input_v3_set_user_data(text_input->text_input, text_input);
zwp_text_input_v3_add_listener(text_input->text_input,
&text_input_listener, text_input);
d->input->text_input = text_input;
}
}
void
Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
{
@@ -1245,6 +1374,16 @@ Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
}
}
void
Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
{
d->text_input_manager = wl_registry_bind(d->registry, id, &zwp_text_input_manager_v3_interface, 1);
if (d->input != NULL) {
Wayland_create_text_input(d);
}
}
void
Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
{
@@ -1263,6 +1402,9 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
if (d->data_device_manager != NULL) {
Wayland_create_data_device(d);
}
if (d->text_input_manager != NULL) {
Wayland_create_text_input(d);
}
wl_seat_add_listener(input->seat, &seat_listener, input);
wl_seat_set_user_data(input->seat, input);
@@ -1291,6 +1433,11 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
SDL_free(input->data_device);
}
if (input->text_input != NULL) {
zwp_text_input_v3_destroy(input->text_input->text_input);
SDL_free(input->text_input);
}
if (input->keyboard)
wl_keyboard_destroy(input->keyboard);
@@ -1575,7 +1722,7 @@ int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *inp
zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(d->key_inhibitor_manager,
w->surface,
input->seat);
return 0;
}

View File

@@ -27,6 +27,7 @@
#include "SDL_waylandvideo.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylanddatamanager.h"
#include "SDL_waylandkeyboard.h"
typedef struct {
// repeat_rate in range of [1, 1000]
@@ -47,6 +48,7 @@ struct SDL_WaylandInput {
struct wl_touch *touch;
struct wl_keyboard *keyboard;
SDL_WaylandDataDevice *data_device;
SDL_WaylandTextInput *text_input;
struct zwp_relative_pointer_v1 *relative_pointer;
struct zwp_confined_pointer_v1 *confined_pointer;
SDL_Window *confined_pointer_window;
@@ -83,6 +85,7 @@ struct SDL_WaylandInput {
extern void Wayland_PumpEvents(_THIS);
extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
extern void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version);
extern void Wayland_display_destroy_input(SDL_VideoData *d);

View File

@@ -24,12 +24,17 @@
#include "../SDL_sysvideo.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "text-input-unstable-v3-client-protocol.h"
int
Wayland_InitKeyboard(_THIS)
{
#ifdef SDL_USE_IME
SDL_IME_Init();
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata->text_input_manager == NULL) {
SDL_IME_Init();
}
#endif
return 0;
@@ -39,37 +44,106 @@ void
Wayland_QuitKeyboard(_THIS)
{
#ifdef SDL_USE_IME
SDL_IME_Quit();
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata->text_input_manager == NULL) {
SDL_IME_Quit();
}
#endif
}
void
Wayland_StartTextInput(_THIS)
{
/* No-op */
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata->text_input_manager) {
struct SDL_WaylandInput *input = driverdata->input;
if (input != NULL && input->text_input) {
const SDL_Rect *rect = &input->text_input->cursor_rect;
/* For some reason this has to be done twice, it appears to be a
* bug in mutter? Maybe?
* -flibit
*/
zwp_text_input_v3_enable(input->text_input->text_input);
zwp_text_input_v3_commit(input->text_input->text_input);
zwp_text_input_v3_enable(input->text_input->text_input);
zwp_text_input_v3_commit(input->text_input->text_input);
/* Now that it's enabled, set the input properties */
zwp_text_input_v3_set_content_type(input->text_input->text_input,
ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
if (!SDL_RectEmpty(rect)) {
/* This gets reset on enable so we have to cache it */
zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input,
rect->x,
rect->y,
rect->w,
rect->h);
}
zwp_text_input_v3_commit(input->text_input->text_input);
}
}
}
void
Wayland_StopTextInput(_THIS)
{
SDL_VideoData *driverdata = _this->driverdata;
if (driverdata->text_input_manager) {
struct SDL_WaylandInput *input = driverdata->input;
if (input != NULL && input->text_input) {
zwp_text_input_v3_disable(input->text_input->text_input);
zwp_text_input_v3_commit(input->text_input->text_input);
}
}
#ifdef SDL_USE_IME
SDL_IME_Reset();
else {
SDL_IME_Reset();
}
#endif
}
void
Wayland_SetTextInputRect(_THIS, SDL_Rect *rect)
{
SDL_VideoData *driverdata = _this->driverdata;
if (!rect) {
SDL_InvalidParamError("rect");
return;
}
if (driverdata->text_input_manager) {
struct SDL_WaylandInput *input = driverdata->input;
if (input != NULL && input->text_input) {
SDL_memcpy(&input->text_input->cursor_rect, rect, sizeof(SDL_Rect));
zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input,
rect->x,
rect->y,
rect->w,
rect->h);
zwp_text_input_v3_commit(input->text_input->text_input);
}
}
#ifdef SDL_USE_IME
SDL_IME_UpdateTextRect(rect);
else {
SDL_IME_UpdateTextRect(rect);
}
#endif
}
SDL_bool
Wayland_HasScreenKeyboardSupport(_THIS)
{
SDL_VideoData *driverdata = _this->driverdata;
return (driverdata->text_input_manager != NULL);
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -23,11 +23,18 @@
#ifndef SDL_waylandkeyboard_h_
#define SDL_waylandkeyboard_h_
typedef struct SDL_WaylandTextInput
{
struct zwp_text_input_v3 *text_input;
SDL_Rect cursor_rect;
} SDL_WaylandTextInput;
extern int Wayland_InitKeyboard(_THIS);
extern void Wayland_QuitKeyboard(_THIS);
extern void Wayland_StartTextInput(_THIS);
extern void Wayland_StopTextInput(_THIS);
extern void Wayland_SetTextInputRect(_THIS, SDL_Rect *rect);
extern SDL_bool Wayland_HasScreenKeyboardSupport(_THIS);
#endif /* SDL_waylandkeyboard_h_ */

View File

@@ -27,7 +27,6 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include "../SDL_sysvideo.h"
@@ -37,7 +36,6 @@
#include "SDL_waylandvideo.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylanddyn.h"
#include "wayland-cursor.h"
@@ -148,14 +146,14 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
cursor = SDL_calloc(1, sizeof (*cursor));
if (cursor) {
SDL_VideoDevice *vd = SDL_GetVideoDevice ();
SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
Wayland_CursorData *data = SDL_calloc (1, sizeof (Wayland_CursorData));
if (!data) {
SDL_OutOfMemory();
free(cursor);
SDL_free(cursor);
return NULL;
}
cursor->driverdata = (void *) data;
@@ -170,8 +168,8 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
surface->h,
WL_SHM_FORMAT_ARGB8888) < 0)
{
free (cursor->driverdata);
free (cursor);
SDL_free (cursor->driverdata);
SDL_free (cursor);
return NULL;
}
@@ -198,12 +196,12 @@ CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
{
SDL_Cursor *cursor;
cursor = calloc(1, sizeof (*cursor));
cursor = SDL_calloc(1, sizeof (*cursor));
if (cursor) {
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
Wayland_CursorData *data = SDL_calloc (1, sizeof (Wayland_CursorData));
if (!data) {
SDL_OutOfMemory();
free(cursor);
SDL_free(cursor);
return NULL;
}
cursor->driverdata = (void *) data;
@@ -309,7 +307,7 @@ Wayland_FreeCursor(SDL_Cursor *cursor)
wl_surface_destroy(d->surface);
/* Not sure what's meant to happen to shm_data */
free (cursor->driverdata);
SDL_free (cursor->driverdata);
SDL_free(cursor);
}

View File

@@ -30,10 +30,8 @@
#include "SDL_waylandopengles.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylanddyn.h"
#include "xdg-shell-client-protocol.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
/* EGL implementation of SDL OpenGL ES support */
@@ -41,12 +39,12 @@ int
Wayland_GLES_LoadLibrary(_THIS, const char *path) {
int ret;
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0);
Wayland_PumpEvents(_this);
WAYLAND_wl_display_flush(data->display);
return ret;
}
@@ -57,6 +55,7 @@ Wayland_GLES_CreateContext(_THIS, SDL_Window * window)
SDL_GLContext context;
context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
return context;
}
@@ -114,19 +113,45 @@ Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
const int swap_interval = _this->egl_data->egl_swapinterval;
/* For windows that we know are hidden, skip swaps entirely, if we don't do
* this compositors will intentionally stall us indefinitely and there's no
* way for an end user to show the window, unlike other situations (i.e.
* the window is minimized, behind another window, etc.).
*
* FIXME: Request EGL_WAYLAND_swap_buffers_with_timeout.
* -flibit
*/
if (window->flags & SDL_WINDOW_HIDDEN) {
return 0;
}
/* Control swap interval ourselves. See comments on Wayland_GLES_SetSwapInterval */
if (swap_interval != 0) {
struct wl_display *display = ((SDL_VideoData *)_this->driverdata)->display;
SDL_VideoDisplay *sdldisplay = SDL_GetDisplayForWindow(window);
const Uint32 max_wait = SDL_GetTicks() + (10000 / sdldisplay->current_mode.refresh_rate); /* ~10 frames, so we'll progress even if throttled to zero. */
while ((SDL_AtomicGet(&data->swap_interval_ready) == 0) && (!SDL_TICKS_PASSED(SDL_GetTicks(), max_wait))) {
while (SDL_AtomicGet(&data->swap_interval_ready) == 0) {
Uint32 now;
/* !!! FIXME: this is just the crucial piece of Wayland_PumpEvents */
WAYLAND_wl_display_flush(display);
if (SDL_IOReady(WAYLAND_wl_display_get_fd(display), SDL_FALSE, 0)) {
WAYLAND_wl_display_dispatch(display);
} else {
WAYLAND_wl_display_dispatch_pending(display);
if (WAYLAND_wl_display_dispatch_pending(display) > 0) {
/* We dispatched some pending events. Check if the frame callback happened. */
continue;
}
now = SDL_GetTicks();
if (SDL_TICKS_PASSED(now, max_wait)) {
/* Timeout expired */
break;
}
if (SDL_IOReady(WAYLAND_wl_display_get_fd(display), SDL_FALSE, max_wait - now) <= 0) {
/* Error or timeout expired without any events for us */
break;
}
WAYLAND_wl_display_dispatch(display);
}
SDL_AtomicSet(&data->swap_interval_ready, 0);
}
@@ -136,9 +161,6 @@ Wayland_GLES_SwapWindow(_THIS, SDL_Window *window)
return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
}
// Wayland-EGL forbids drawing calls in-between SwapBuffers and wl_egl_window_resize
Wayland_HandlePendingResize(window);
WAYLAND_wl_display_flush( data->waylandData->display );
return 0;
@@ -148,14 +170,14 @@ int
Wayland_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
int ret;
if (window && context) {
ret = SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
}
else {
ret = SDL_EGL_MakeCurrent(_this, NULL, NULL);
}
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
_this->egl_data->eglSwapInterval(_this->egl_data->egl_display, 0); /* see comments on Wayland_GLES_SetSwapInterval. */
@@ -180,7 +202,7 @@ Wayland_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
}
}
void
void
Wayland_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_EGL_DeleteContext(_this, context);

View File

@@ -33,6 +33,8 @@
#define SDL_WAYLAND_INTERFACE(iface)
#endif
#include <stdbool.h>
SDL_WAYLAND_MODULE(WAYLAND_CLIENT)
SDL_WAYLAND_SYM(void, wl_proxy_marshal, (struct wl_proxy *, uint32_t, ...))
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_create, (struct wl_proxy *, const struct wl_interface *))
@@ -71,18 +73,20 @@ SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_prox
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_INTERFACE(wl_seat_interface)
SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
SDL_WAYLAND_INTERFACE(wl_buffer_interface)
SDL_WAYLAND_INTERFACE(wl_registry_interface)
SDL_WAYLAND_INTERFACE(wl_shell_surface_interface)
SDL_WAYLAND_INTERFACE(wl_region_interface)
SDL_WAYLAND_INTERFACE(wl_pointer_interface)
SDL_WAYLAND_INTERFACE(wl_keyboard_interface)
SDL_WAYLAND_INTERFACE(wl_compositor_interface)
SDL_WAYLAND_INTERFACE(wl_output_interface)
SDL_WAYLAND_INTERFACE(wl_shell_interface)
SDL_WAYLAND_INTERFACE(wl_shm_interface)
SDL_WAYLAND_INTERFACE(wl_data_device_interface)
SDL_WAYLAND_INTERFACE(wl_data_source_interface)
@@ -134,6 +138,61 @@ SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
const xkb_keysym_t **) )
SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )
#ifdef HAVE_LIBDECOR_H
SDL_WAYLAND_MODULE(WAYLAND_LIBDECOR)
SDL_WAYLAND_SYM(void, libdecor_unref, (struct libdecor *))
SDL_WAYLAND_SYM(struct libdecor *, libdecor_new, (struct wl_display *, struct libdecor_interface *))
SDL_WAYLAND_SYM(struct libdecor_frame *, libdecor_decorate, (struct libdecor *,\
struct wl_surface *,\
struct libdecor_frame_interface *,\
void *))
SDL_WAYLAND_SYM(void, libdecor_frame_unref, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_title, (struct libdecor_frame *, const char *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_app_id, (struct libdecor_frame *, const char *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_max_content_size, (struct libdecor_frame *frame,\
int content_width,\
int content_height))
SDL_WAYLAND_SYM(void, libdecor_frame_set_min_content_size, (struct libdecor_frame *frame,\
int content_width,\
int content_height))
SDL_WAYLAND_SYM(void, libdecor_frame_resize, (struct libdecor_frame *,\
struct wl_seat *,\
uint32_t,\
enum libdecor_resize_edge))
SDL_WAYLAND_SYM(void, libdecor_frame_move, (struct libdecor_frame *,\
struct wl_seat *,\
uint32_t))
SDL_WAYLAND_SYM(void, libdecor_frame_commit, (struct libdecor_frame *,\
struct libdecor_state *,\
struct libdecor_configuration *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_minimized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_maximized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_maximized, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_fullscreen, (struct libdecor_frame *, struct wl_output *))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_fullscreen, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_capabilities, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(void, libdecor_frame_unset_capabilities, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(bool, libdecor_frame_has_capability, (struct libdecor_frame *, \
enum libdecor_capabilities))
SDL_WAYLAND_SYM(void, libdecor_frame_set_visibility, (struct libdecor_frame *, bool))
SDL_WAYLAND_SYM(bool, libdecor_frame_is_visible, (struct libdecor_frame *))
SDL_WAYLAND_SYM(bool, libdecor_frame_is_floating, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_set_parent, (struct libdecor_frame *,\
struct libdecor_frame *))
SDL_WAYLAND_SYM(struct xdg_surface *, libdecor_frame_get_xdg_surface, (struct libdecor_frame *))
SDL_WAYLAND_SYM(void, libdecor_frame_map, (struct libdecor_frame *))
SDL_WAYLAND_SYM(struct libdecor_state *, libdecor_state_new, (int, int))
SDL_WAYLAND_SYM(void, libdecor_state_free, (struct libdecor_state *))
SDL_WAYLAND_SYM(bool, libdecor_configuration_get_content_size, (struct libdecor_configuration *,\
struct libdecor_frame *,\
int *,\
int *))
SDL_WAYLAND_SYM(bool, libdecor_configuration_get_window_state, (struct libdecor_configuration *,\
enum libdecor_window_state *))
#endif
#undef SDL_WAYLAND_MODULE
#undef SDL_WAYLAND_SYM
#undef SDL_WAYLAND_INTERFACE

View File

@@ -30,7 +30,6 @@
#include <stdint.h>
#include <stddef.h>
#include "wayland-util.h"
#include "SDL_waylanddyn.h"
void Wayland_touch_create(SDL_VideoData *data, uint32_t id);

View File

@@ -37,21 +37,25 @@
#include "SDL_waylandtouch.h"
#include "SDL_waylandclipboard.h"
#include "SDL_waylandvulkan.h"
#include "SDL_hints.h"
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <xkbcommon/xkbcommon.h>
#include "SDL_waylanddyn.h"
#include <wayland-util.h>
#include "xdg-shell-client-protocol.h"
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
#endif
#define WAYLANDVID_DRIVER_NAME "wayland"
@@ -124,6 +128,39 @@ get_classname()
return SDL_strdup("SDL_App");
}
static const char *SDL_WAYLAND_surface_tag = "sdl-window";
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);
}
}
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);
}
}
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... */
}
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... */
}
static void
Wayland_DeleteDevice(SDL_VideoDevice *device)
{
@@ -217,6 +254,7 @@ Wayland_CreateDevice(int devindex)
device->DestroyWindow = Wayland_DestroyWindow;
device->SetWindowHitTest = Wayland_SetWindowHitTest;
device->FlashWindow = Wayland_FlashWindow;
device->HasScreenKeyboardSupport = Wayland_HasScreenKeyboardSupport;
device->SetClipboardText = Wayland_SetClipboardText;
device->GetClipboardText = Wayland_GetClipboardText;
@@ -389,6 +427,7 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
data->scale_factor = 1.0;
wl_output_add_listener(output, &output_listener, data);
SDL_WAYLAND_register_output(output);
}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
@@ -410,18 +449,6 @@ static const struct qt_windowmanager_listener windowmanager_listener = {
};
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
static void
handle_ping_zxdg_shell(void *data, struct zxdg_shell_v6 *zxdg, uint32_t serial)
{
zxdg_shell_v6_pong(zxdg, serial);
}
static const struct zxdg_shell_v6_listener shell_listener_zxdg = {
handle_ping_zxdg_shell
};
static void
handle_ping_xdg_wm_base(void *data, struct xdg_wm_base *xdg, uint32_t serial)
{
@@ -433,6 +460,21 @@ static const struct xdg_wm_base_listener shell_listener_xdg = {
};
#ifdef HAVE_LIBDECOR_H
static void
libdecor_error(struct libdecor *context,
enum libdecor_error error,
const char *message)
{
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "libdecor error (%d): %s\n", error, message);
}
static struct libdecor_interface libdecor_interface = {
libdecor_error,
};
#endif
static void
display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
@@ -441,45 +483,42 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
/*printf("WAYLAND INTERFACE: %s\n", interface);*/
if (strcmp(interface, "wl_compositor") == 0) {
if (SDL_strcmp(interface, "wl_compositor") == 0) {
d->compositor = wl_registry_bind(d->registry, id, &wl_compositor_interface, SDL_min(3, version));
} else if (strcmp(interface, "wl_output") == 0) {
} else if (SDL_strcmp(interface, "wl_output") == 0) {
Wayland_add_display(d, id);
} else if (strcmp(interface, "wl_seat") == 0) {
} else if (SDL_strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id, version);
} else if (strcmp(interface, "xdg_wm_base") == 0) {
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
} else if (strcmp(interface, "zxdg_shell_v6") == 0) {
d->shell.zxdg = wl_registry_bind(d->registry, id, &zxdg_shell_v6_interface, 1);
zxdg_shell_v6_add_listener(d->shell.zxdg, &shell_listener_zxdg, NULL);
} else if (strcmp(interface, "wl_shell") == 0) {
d->shell.wl = wl_registry_bind(d->registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm);
} else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
} else if (SDL_strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
Wayland_display_add_relative_pointer_manager(d, id);
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
} else if (SDL_strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
Wayland_display_add_pointer_constraints(d, id);
} else if (strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) {
} else if (SDL_strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) {
d->key_inhibitor_manager = wl_registry_bind(d->registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
} else if (SDL_strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
d->idle_inhibit_manager = wl_registry_bind(d->registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
} else if (strcmp(interface, "xdg_activation_v1") == 0) {
} else if (SDL_strcmp(interface, "xdg_activation_v1") == 0) {
d->activation_manager = wl_registry_bind(d->registry, id, &xdg_activation_v1_interface, 1);
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
} else if (strcmp(interface, "zwp_text_input_manager_v3") == 0) {
Wayland_add_text_input_manager(d, id, version);
} else if (SDL_strcmp(interface, "wl_data_device_manager") == 0) {
Wayland_add_data_device_manager(d, id, version);
} else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
} 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);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) {
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id);
} else if (strcmp(interface, "qt_surface_extension") == 0) {
} else if (SDL_strcmp(interface, "qt_surface_extension") == 0) {
d->surface_extension = wl_registry_bind(registry, id,
&qt_surface_extension_interface, 1);
} else if (strcmp(interface, "qt_windowmanager") == 0) {
} else if (SDL_strcmp(interface, "qt_windowmanager") == 0) {
d->windowmanager = wl_registry_bind(registry, id,
&qt_windowmanager_interface, 1);
qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d);
@@ -515,6 +554,19 @@ Wayland_VideoInit(_THIS)
// First roundtrip to receive all registry objects.
WAYLAND_wl_display_roundtrip(data->display);
#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)) {
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
// Second roundtrip to receive all output events.
WAYLAND_wl_display_roundtrip(data->display);
@@ -527,10 +579,6 @@ Wayland_VideoInit(_THIS)
Wayland_InitKeyboard(_this);
#if SDL_USE_LIBDBUS
SDL_DBus_Init();
#endif
return 0;
}
@@ -597,6 +645,11 @@ Wayland_VideoQuit(_THIS)
if (data->key_inhibitor_manager)
zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(data->key_inhibitor_manager);
Wayland_QuitKeyboard(_this);
if (data->text_input_manager)
zwp_text_input_manager_v3_destroy(data->text_input_manager);
if (data->xkb_context) {
WAYLAND_xkb_context_unref(data->xkb_context);
data->xkb_context = NULL;
@@ -620,26 +673,25 @@ Wayland_VideoQuit(_THIS)
if (data->cursor_theme)
WAYLAND_wl_cursor_theme_destroy(data->cursor_theme);
if (data->shell.wl)
wl_shell_destroy(data->shell.wl);
if (data->shell.xdg)
xdg_wm_base_destroy(data->shell.xdg);
if (data->shell.zxdg)
zxdg_shell_v6_destroy(data->shell.zxdg);
if (data->decoration_manager)
zxdg_decoration_manager_v1_destroy(data->decoration_manager);
#ifdef HAVE_LIBDECOR_H
if (data->shell.libdecor) {
libdecor_unref(data->shell.libdecor);
data->shell.libdecor = NULL;
}
#endif
if (data->compositor)
wl_compositor_destroy(data->compositor);
if (data->registry)
wl_registry_destroy(data->registry);
Wayland_QuitKeyboard(_this);
SDL_free(data->classname);
}

View File

@@ -25,15 +25,6 @@
#ifndef SDL_waylandvideo_h_
#define SDL_waylandvideo_h_
/*
!!! FIXME: xdg_wm_base is the stable replacement for zxdg_shell_v6. While it's
!!! FIXME: harmless to leave it here, consider deleting the obsolete codepath
!!! FIXME: soon, since Wayland (with xdg_wm_base) will probably be mainline
!!! FIXME: by the time people are relying on this SDL target. It's available
!!! FIXME: in Ubuntu 18.04 (and other distros).
*/
#include <EGL/egl.h>
#include "wayland-util.h"
@@ -60,8 +51,9 @@ typedef struct {
struct wl_pointer *pointer;
struct {
struct xdg_wm_base *xdg;
struct zxdg_shell_v6 *zxdg;
struct wl_shell *wl;
#ifdef HAVE_LIBDECOR_H
struct libdecor *libdecor;
#endif
} shell;
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
@@ -70,6 +62,7 @@ typedef struct {
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
struct xdg_activation_v1 *activation_manager;
struct zwp_text_input_manager_v3 *text_input_manager;
EGLDisplay edpy;
EGLContext context;
@@ -99,6 +92,14 @@ typedef struct {
SDL_bool done;
} SDL_WaylandOutputData;
/* Needed here to get wl_surface declaration, fixes GitHub#4594 */
#include "SDL_waylanddyn.h"
extern void SDL_WAYLAND_register_surface(struct wl_surface *surface);
extern void SDL_WAYLAND_register_output(struct wl_output *output);
extern SDL_bool SDL_WAYLAND_own_surface(struct wl_surface *surface);
extern SDL_bool SDL_WAYLAND_own_output(struct wl_output *output);
#endif /* SDL_waylandvideo_h_ */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load Diff

View File

@@ -32,15 +32,6 @@
struct SDL_WaylandInput;
typedef struct {
struct zxdg_surface_v6 *surface;
union {
struct zxdg_toplevel_v6 *toplevel;
struct zxdg_popup_v6 *popup;
} roleobj;
SDL_bool initial_configure_seen;
} SDL_zxdg_shell_surface;
typedef struct {
struct xdg_surface *surface;
union {
@@ -50,15 +41,23 @@ typedef struct {
SDL_bool initial_configure_seen;
} SDL_xdg_shell_surface;
#ifdef HAVE_LIBDECOR_H
typedef struct {
struct libdecor_frame *frame;
SDL_bool initial_configure_seen;
} SDL_libdecor_surface;
#endif
typedef struct {
SDL_Window *sdlwindow;
SDL_VideoData *waylandData;
struct wl_surface *surface;
struct wl_callback *frame_callback;
union {
#ifdef HAVE_LIBDECOR_H
SDL_libdecor_surface libdecor;
#endif
SDL_xdg_shell_surface xdg;
SDL_zxdg_shell_surface zxdg;
struct wl_shell_surface *wl;
} shell_surface;
struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device;
@@ -69,20 +68,16 @@ typedef struct {
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
struct xdg_activation_token_v1 *activation_token;
/* floating dimensions for restoring from maximized and fullscreen */
int floating_width, floating_height;
SDL_atomic_t swap_interval_ready;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct qt_extended_surface *extended_surface;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
struct {
SDL_bool pending, configure;
uint32_t serial;
int width, height;
float scale_factor;
} resize;
struct wl_output **outputs;
SDL_WaylandOutputData **outputs;
int num_outputs;
float scale_factor;
@@ -113,9 +108,7 @@ extern void Wayland_SuspendScreenSaver(_THIS);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern int Wayland_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
extern void Wayland_HandlePendingResize(SDL_Window *window);
extern int Wayland_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation);
#endif /* SDL_waylandwindow_h_ */

View File

@@ -294,31 +294,31 @@ WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mou
}
static void
WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data, SDL_MouseID mouseID)
{
if (rawButtons != data->mouse_button_flags) {
Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0);
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, 0);
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), mouseFlags, swapButtons, data, SDL_BUTTON_LEFT, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0);
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, 0);
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), mouseFlags, swapButtons, data, SDL_BUTTON_RIGHT, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0);
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, 0);
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), mouseFlags, swapButtons, data, SDL_BUTTON_MIDDLE, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0);
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, 0);
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X1, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID);
if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), mouseFlags, swapButtons, data, SDL_BUTTON_X2, mouseID);
data->mouse_button_flags = rawButtons;
}
}
@@ -714,15 +714,17 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
if (inp.header.dwType == RIM_TYPEMOUSE) {
SDL_MouseID mouseID;
if (SDL_GetNumTouchDevices() > 0 &&
(GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x82) == 0x82)) {
break;
}
mouseID = (SDL_MouseID)(uintptr_t)inp.header.hDevice;
if (isRelative) {
RAWMOUSE* rawmouse = &inp.data.mouse;
if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
SDL_SendMouseMotion(data->window, mouseID, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
} else if (rawmouse->lLastX || rawmouse->lLastY) {
/* synthesize relative moves from the abs position */
static SDL_Point lastMousePoint;
@@ -737,12 +739,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
lastMousePoint.y = y;
}
SDL_SendMouseMotion(data->window, 0, 1, (int)(x-lastMousePoint.x), (int)(y-lastMousePoint.y));
SDL_SendMouseMotion(data->window, mouseID, 1, (int)(x-lastMousePoint.x), (int)(y-lastMousePoint.y));
lastMousePoint.x = x;
lastMousePoint.y = y;
}
WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data);
WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data, mouseID);
} else if (isCapture) {
/* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
POINT pt;
@@ -758,12 +760,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
SDL_SendMouseMotion(data->window, 0, 0, (int)pt.x, (int)pt.y);
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT);
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT);
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
SDL_SendMouseMotion(data->window, mouseID, 0, (int)pt.x, (int)pt.y);
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT);
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT);
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
}
} else {
SDL_assert(0 && "Shouldn't happen");
@@ -961,6 +963,14 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Fix our size to the current size */
info = (MINMAXINFO *) lParam;
if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_BORDERLESS) {
int screenW = GetSystemMetrics(SM_CXSCREEN);
int screenH = GetSystemMetrics(SM_CYSCREEN);
info->ptMaxSize.x = SDL_max(w, screenW);
info->ptMaxSize.y = SDL_max(h, screenH);
info->ptMaxPosition.x = SDL_min(0, ((screenW - w) / 2));
info->ptMaxPosition.y = SDL_min(0, ((screenH - h) / 2));
}
info->ptMinTrackSize.x = w + min_w;
info->ptMinTrackSize.y = h + min_h;
if (constrain_max_size) {
@@ -1363,6 +1373,13 @@ WIN_PumpEvents(_THIS)
if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
}
/* The Windows key state gets lost when using Windows+Space or Windows+G shortcuts */
if ((keystate[SDL_SCANCODE_LGUI] == SDL_PRESSED) && !(GetKeyState(VK_LWIN) & 0x8000)) {
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LGUI);
}
if ((keystate[SDL_SCANCODE_RGUI] == SDL_PRESSED) && !(GetKeyState(VK_RWIN) & 0x8000)) {
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RGUI);
}
/* Update the clipping rect in case someone else has stolen it */
WIN_UpdateClipCursorForWindows();

View File

@@ -31,7 +31,7 @@ HCURSOR SDL_cursor = NULL;
static int rawInputEnableCount = 0;
static int
static int
ToggleRawInput(SDL_bool enabled)
{
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
@@ -57,6 +57,9 @@ ToggleRawInput(SDL_bool enabled)
/* (Un)register raw input for mice */
if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
/* Reset the enable count, otherwise subsequent enable calls will
believe raw input is enabled */
rawInputEnableCount = 0;
/* Only return an error when registering. If we unregister and fail,
then it's probably that we unregistered twice. That's OK. */

View File

@@ -108,7 +108,10 @@ WIN_GLES_SetupWindow(_THIS, SDL_Window * window)
SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
if (_this->egl_data == NULL) {
/* !!! FIXME: commenting out this assertion is (I think) incorrect; figure out why driver_loaded is wrong for ANGLE instead. --ryan. */
#if 0 /* When hint SDL_HINT_OPENGL_ES_DRIVER is set to "1" (e.g. for ANGLE support), _this->gl_config.driver_loaded can be 0, while the below lines function. */
SDL_assert(!_this->gl_config.driver_loaded);
#endif
if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) {
SDL_EGL_UnloadLibrary(_this);
return -1;

View File

@@ -162,7 +162,7 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
top = HWND_NOTOPMOST;
}
WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
data->expected_resize = SDL_TRUE;
SetWindowPos(hwnd, top, x, y, w, h, flags);
@@ -364,7 +364,7 @@ WIN_CreateWindow(_THIS, SDL_Window * window)
return 0;
#else
return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
#endif /* SDL_VIDEO_OPENGL_EGL */
#endif /* SDL_VIDEO_OPENGL_EGL */
}
#endif /* SDL_VIDEO_OPENGL_ES2 */
@@ -559,7 +559,7 @@ WIN_ShowWindow(_THIS, SDL_Window * window)
DWORD style;
HWND hwnd;
int nCmdShow;
hwnd = ((SDL_WindowData *)window->driverdata)->hwnd;
nCmdShow = SW_SHOW;
style = GetWindowLong(hwnd, GWL_EXSTYLE);
@@ -992,33 +992,12 @@ WIN_UpdateClipCursor(SDL_Window *window)
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
if (mouse->relative_mode && !mouse->relative_mode_warp) {
if (GetWindowRect(data->hwnd, &rect)) {
LONG cx, cy;
cx = (rect.left + rect.right) / 2;
cy = (rect.top + rect.bottom) / 2;
/* Make an absurdly small clip rect */
rect.left = cx - 1;
rect.right = cx + 1;
rect.top = cy - 1;
rect.bottom = cy + 1;
if (SDL_memcmp(&rect, &clipped_rect, sizeof(rect)) != 0) {
if (ClipCursor(&rect)) {
data->cursor_clipped_rect = rect;
}
}
}
} else {
if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
ClientToScreen(data->hwnd, (LPPOINT) & rect);
ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
if (SDL_memcmp(&rect, &clipped_rect, sizeof(rect)) != 0) {
if (ClipCursor(&rect)) {
data->cursor_clipped_rect = rect;
}
if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
ClientToScreen(data->hwnd, (LPPOINT) & rect);
ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
if (SDL_memcmp(&rect, &clipped_rect, sizeof(rect)) != 0) {
if (ClipCursor(&rect)) {
data->cursor_clipped_rect = rect;
}
}
}
@@ -1085,17 +1064,27 @@ WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
}
int
WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count)
WIN_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation)
{
HWND hwnd;
FLASHWINFO desc;
hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
SDL_zero(desc);
desc.cbSize = sizeof(desc);
desc.hwnd = hwnd;
desc.dwFlags = FLASHW_TRAY;
desc.uCount = flash_count; /* flash x times */
desc.dwTimeout = 0;
desc.hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
switch (operation) {
case SDL_FLASH_CANCEL:
desc.dwFlags = FLASHW_STOP;
break;
case SDL_FLASH_BRIEFLY:
desc.dwFlags = FLASHW_TRAY;
desc.uCount = 1;
break;
case SDL_FLASH_UNTIL_FOCUSED:
desc.dwFlags = (FLASHW_TRAY | FLASHW_TIMERNOFG);
break;
default:
return SDL_Unsupported();
}
FlashWindowEx(&desc);

View File

@@ -86,7 +86,7 @@ extern void WIN_OnWindowEnter(_THIS, SDL_Window * window);
extern void WIN_UpdateClipCursor(SDL_Window *window);
extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
extern int WIN_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation);
#endif /* SDL_windowswindow_h_ */

View File

@@ -122,7 +122,8 @@ WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *b
using namespace Windows::UI::Input;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
return SDL_BUTTON_LEFT;
*button = SDL_BUTTON_LEFT;
return SDL_TRUE;
#else
switch (pt->Properties->PointerUpdateKind)
{

View File

@@ -28,6 +28,12 @@
was based off of SDL's "dummy" video driver.
*/
/* Standard C++11 includes */
#include <functional>
#include <string>
#include <sstream>
using namespace std;
/* Windows includes */
#include <agile.h>
#include <windows.graphics.display.h>
@@ -67,6 +73,7 @@ extern "C" {
#include "SDL_winrtmouse_c.h"
#include "SDL_main.h"
#include "SDL_system.h"
#include "SDL_hints.h"
/* Initialization/Query functions */
@@ -171,6 +178,68 @@ VideoBootStrap WINRT_bootstrap = {
WINRT_CreateDevice
};
static void SDLCALL
WINRT_SetDisplayOrientationsPreference(void *userdata, const char *name, const char *oldValue, const char *newValue)
{
SDL_assert(SDL_strcmp(name, SDL_HINT_ORIENTATIONS) == 0);
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
* from being changed on startup, by detecting when SDL_HINT_ORIENTATIONS
* is getting registered.
*
* TODO, WinRT: consider reading in an app's .appxmanifest file, and apply its orientation when 'newValue == NULL'.
*/
if ((oldValue == NULL) && (newValue == NULL)) {
return;
}
// Start with no orientation flags, then add each in as they're parsed
// from newValue.
unsigned int orientationFlags = 0;
if (newValue) {
std::istringstream tokenizer(newValue);
while (!tokenizer.eof()) {
std::string orientationName;
std::getline(tokenizer, orientationName, ' ');
if (orientationName == "LandscapeLeft") {
orientationFlags |= (unsigned int) DisplayOrientations::LandscapeFlipped;
} else if (orientationName == "LandscapeRight") {
orientationFlags |= (unsigned int) DisplayOrientations::Landscape;
} else if (orientationName == "Portrait") {
orientationFlags |= (unsigned int) DisplayOrientations::Portrait;
} else if (orientationName == "PortraitUpsideDown") {
orientationFlags |= (unsigned int) DisplayOrientations::PortraitFlipped;
}
}
}
// If no valid orientation flags were specified, use a reasonable set of defaults:
if (!orientationFlags) {
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
orientationFlags = (unsigned int) ( \
DisplayOrientations::Landscape |
DisplayOrientations::LandscapeFlipped |
DisplayOrientations::Portrait |
DisplayOrientations::PortraitFlipped);
}
// Set the orientation/rotation preferences. Please note that this does
// not constitute a 100%-certain lock of a given set of possible
// orientations. According to Microsoft's documentation on WinRT [1]
// when a device is not capable of being rotated, Windows may ignore
// the orientation preferences, and stick to what the device is capable of
// displaying.
//
// [1] Documentation on the 'InitialRotationPreference' setting for a
// Windows app's manifest file describes how some orientation/rotation
// preferences may be ignored. See
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
// for details. Microsoft's "Display orientation sample" also gives an
// outline of how Windows treats device rotation
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
WINRT_DISPLAY_PROPERTY(AutoRotationPreferences) = (DisplayOrientations) orientationFlags;
}
int
WINRT_VideoInit(_THIS)
{
@@ -178,6 +247,11 @@ WINRT_VideoInit(_THIS)
if (WINRT_InitModes(_this) < 0) {
return -1;
}
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
// TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, WINRT_SetDisplayOrientationsPreference, NULL);
WINRT_InitMouse(_this);
WINRT_InitTouch(_this);
WINRT_InitGameBar(_this);

View File

@@ -27,14 +27,7 @@
#include "SDL_events.h"
#include "SDL_x11video.h"
#include "SDL_timer.h"
/* If you don't support UTF-8, you might use XA_STRING here */
#ifdef X_HAVE_UTF8_STRING
#define TEXT_FORMAT X11_XInternAtom(display, "UTF8_STRING", False)
#else
#define TEXT_FORMAT XA_STRING
#endif
#include "SDL_x11clipboard.h"
/* Get any application owned window handle for clipboard association */
static Window
@@ -59,19 +52,77 @@ GetWindow(_THIS)
return data->clipboard_window;
}
/* We use our own cut-buffer for intermediate storage instead of
XA_CUT_BUFFER0 because their use isn't really defined for holding UTF8. */
Atom
X11_GetSDLCutBufferClipboardType(Display *display)
X11_GetSDLCutBufferClipboardType(Display *display, enum ESDLX11ClipboardMimeType mime_type)
{
return X11_XInternAtom(display, "SDL_CUTBUFFER", False);
switch (mime_type) {
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
#ifdef X_HAVE_UTF8_STRING
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
#endif
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
return X11_XInternAtom(display, "SDL_CUTBUFFER", False);
default:
SDL_SetError("Can't find mime_type.");
return XA_STRING;
}
}
Atom
X11_GetSDLCutBufferClipboardExternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type)
{
switch (mime_type) {
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
/* If you don't support UTF-8, you might use XA_STRING here */
#ifdef X_HAVE_UTF8_STRING
return X11_XInternAtom(display, "UTF8_STRING", False);
#else
return XA_STRING;
#endif
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
return X11_XInternAtom(display, "text/plain", False);
#ifdef X_HAVE_UTF8_STRING
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
return X11_XInternAtom(display, "text/plain;charset=utf-8", False);
#endif
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
return X11_XInternAtom(display, "TEXT", False);
default:
SDL_SetError("Can't find mime_type.");
return XA_STRING;
}
}
Atom
X11_GetSDLCutBufferClipboardInternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type)
{
switch (mime_type) {
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
#ifdef X_HAVE_UTF8_STRING
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
#endif
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
/* If you don't support UTF-8, you might use XA_STRING here */
#ifdef X_HAVE_UTF8_STRING
return X11_XInternAtom(display, "UTF8_STRING", False);
#else
return XA_STRING;
#endif
default:
SDL_SetError("Can't find mime_type.");
return XA_STRING;
}
}
int
X11_SetClipboardText(_THIS, const char *text)
{
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
Atom format;
Window window;
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
@@ -82,9 +133,8 @@ X11_SetClipboardText(_THIS, const char *text)
}
/* Save the selection on the root window */
format = TEXT_FORMAT;
X11_XChangeProperty(display, DefaultRootWindow(display),
X11_GetSDLCutBufferClipboardType(display), format, 8, PropModeReplace,
X11_GetSDLCutBufferClipboardType(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING), X11_GetSDLCutBufferClipboardInternalFormat(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING), 8, PropModeReplace,
(const unsigned char *)text, SDL_strlen(text));
if (XA_CLIPBOARD != None &&
@@ -125,7 +175,7 @@ X11_GetClipboardText(_THIS)
/* Get the window that holds the selection */
window = GetWindow(_this);
format = TEXT_FORMAT;
format = X11_GetSDLCutBufferClipboardInternalFormat(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING);
owner = X11_XGetSelectionOwner(display, XA_CLIPBOARD);
if (owner == None) {
/* Fall back to ancient X10 cut-buffers which do not support UTF8 strings*/
@@ -134,7 +184,7 @@ X11_GetClipboardText(_THIS)
format = XA_STRING;
} else if (owner == window) {
owner = DefaultRootWindow(display);
selection = X11_GetSDLCutBufferClipboardType(display);
selection = X11_GetSDLCutBufferClipboardType(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING);
} else {
/* Request that the selection owner copy the data to our window */
owner = window;

View File

@@ -23,10 +23,22 @@
#ifndef SDL_x11clipboard_h_
#define SDL_x11clipboard_h_
enum ESDLX11ClipboardMimeType {
SDL_X11_CLIPBOARD_MIME_TYPE_STRING,
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN,
#ifdef X_HAVE_UTF8_STRING
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8,
#endif
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT,
SDL_X11_CLIPBOARD_MIME_TYPE_MAX
};
extern int X11_SetClipboardText(_THIS, const char *text);
extern char *X11_GetClipboardText(_THIS);
extern SDL_bool X11_HasClipboardText(_THIS);
extern Atom X11_GetSDLCutBufferClipboardType(Display *display);
extern Atom X11_GetSDLCutBufferClipboardType(Display *display, enum ESDLX11ClipboardMimeType mime_type);
extern Atom X11_GetSDLCutBufferClipboardExternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type);
extern Atom X11_GetSDLCutBufferClipboardInternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type);
#endif /* SDL_x11clipboard_h_ */

View File

@@ -404,6 +404,9 @@ X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
#ifdef SDL_USE_IME
SDL_IME_SetFocus(SDL_TRUE);
#endif
if (data->flashing_window) {
X11_FlashWindow(_this, data->window, SDL_FLASH_CANCEL);
}
}
static void
@@ -559,6 +562,7 @@ X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
static void
X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
{
int i;
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display = videodata->display;
@@ -570,10 +574,12 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
case SelectionRequest: {
const XSelectionRequestEvent *req = &xevent->xselectionrequest;
XEvent sevent;
int seln_format;
int seln_format, mime_formats;
unsigned long nbytes;
unsigned long overflow;
unsigned char *seln_data;
unsigned char *seln_data;
Atom supportedFormats[SDL_X11_CLIPBOARD_MIME_TYPE_MAX+1];
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
#ifdef DEBUG_XEVENTS
printf("window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
@@ -591,27 +597,38 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
/* !!! FIXME: We were probably storing this on the root window
because an SDL window might go away...? but we don't have to do
this now (or ever, really). */
if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
&sevent.xselection.target, &seln_format, &nbytes,
&overflow, &seln_data) == Success) {
/* !!! FIXME: cache atoms */
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
if (sevent.xselection.target == req->target) {
X11_XChangeProperty(display, req->requestor, req->property,
sevent.xselection.target, seln_format, PropModeReplace,
seln_data, nbytes);
sevent.xselection.property = req->property;
} else if (XA_TARGETS == req->target) {
Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
X11_XChangeProperty(display, req->requestor, req->property,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)SupportedFormats,
SDL_arraysize(SupportedFormats));
sevent.xselection.property = req->property;
sevent.xselection.target = XA_TARGETS;
if (req->target == XA_TARGETS) {
supportedFormats[0] = XA_TARGETS;
mime_formats = 1;
for (i = 0; i < SDL_X11_CLIPBOARD_MIME_TYPE_MAX; ++i)
supportedFormats[mime_formats++] = X11_GetSDLCutBufferClipboardExternalFormat(display, i);
X11_XChangeProperty(display, req->requestor, req->property,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)supportedFormats,
mime_formats);
sevent.xselection.property = req->property;
sevent.xselection.target = XA_TARGETS;
} else {
for (i = 0; i < SDL_X11_CLIPBOARD_MIME_TYPE_MAX; ++i) {
if (X11_GetSDLCutBufferClipboardExternalFormat(display, i) != req->target)
continue;
if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
X11_GetSDLCutBufferClipboardType(display, i), 0, INT_MAX/4, False, X11_GetSDLCutBufferClipboardInternalFormat(display, i),
&sevent.xselection.target, &seln_format, &nbytes,
&overflow, &seln_data) == Success) {
if (seln_format != None) {
X11_XChangeProperty(display, req->requestor, req->property,
sevent.xselection.target, seln_format, PropModeReplace,
seln_data, nbytes);
sevent.xselection.property = req->property;
X11_XFree(seln_data);
break;
} else {
X11_XFree(seln_data);
}
}
}
X11_XFree(seln_data);
}
X11_XSendEvent(display, req->requestor, False, 0, &sevent);
X11_XSync(display, False);
@@ -1548,6 +1565,7 @@ X11_PumpEvents(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
XEvent xevent;
int i;
if (data->last_mode_change_deadline) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
@@ -1586,6 +1604,15 @@ X11_PumpEvents(_THIS)
/* FIXME: Only need to do this when there are pending focus changes */
X11_HandleFocusChanges(_this);
/* FIXME: Only need to do this when there are flashing windows */
for (i = 0; i < data->numwindows; ++i) {
if (data->windowlist[i] != NULL &&
data->windowlist[i]->flash_cancel_time &&
SDL_TICKS_PASSED(SDL_GetTicks(), data->windowlist[i]->flash_cancel_time)) {
X11_FlashWindow(_this, data->windowlist[i]->window, SDL_FLASH_CANCEL);
}
}
}

View File

@@ -995,6 +995,15 @@ X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
}
}
/* This catches an error from XRRSetScreenSize, as a workaround for now. */
/* !!! FIXME: remove this later when we have a better solution. */
static int (*PreXRRSetScreenSizeErrorHandler)(Display *, XErrorEvent *) = NULL;
static int
SDL_XRRSetScreenSizeErrHandler(Display *d, XErrorEvent *e)
{
return (e->error_code == BadMatch) ? 0 : PreXRRSetScreenSizeErrorHandler(d, e);
}
int
X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
{
@@ -1002,6 +1011,7 @@ X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode
Display *display = viddata->display;
SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
int mm_width, mm_height;
viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
@@ -1030,10 +1040,35 @@ X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode
return SDL_SetError("Couldn't get XRandR crtc info");
}
X11_XGrabServer(display);
status = X11_XRRSetCrtcConfig(display, res, output_info->crtc, CurrentTime,
0, 0, None, crtc->rotation, NULL, 0);
if (status != Success) {
goto setCrtcError;
}
mm_width = mode->w * DisplayWidthMM(display, data->screen) / DisplayWidth(display, data->screen);
mm_height = mode->h * DisplayHeightMM(display, data->screen) / DisplayHeight(display, data->screen);
/* !!! FIXME: this can get into a problem scenario when a window is
bigger than a physical monitor in a configuration where one screen
spans multiple physical monitors. A detailed reproduction case is
discussed at https://github.com/libsdl-org/SDL/issues/4561 ...
for now we cheat and just catch the X11 error and carry on, which
is likely to cause subtle issues but is better than outright
crashing */
X11_XSync(display, False);
PreXRRSetScreenSizeErrorHandler = X11_XSetErrorHandler(SDL_XRRSetScreenSizeErrHandler);
X11_XRRSetScreenSize(display, RootWindow(display, data->screen), mode->w, mode->h, mm_width, mm_height);
X11_XSync(display, False);
X11_XSetErrorHandler(PreXRRSetScreenSizeErrorHandler);
status = X11_XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation,
&data->xrandr_output, 1);
setCrtcError:
X11_XUngrabServer(display);
X11_XRRFreeCrtcInfo(crtc);
X11_XRRFreeOutputInfo(output_info);
X11_XRRFreeScreenResources(res);

View File

@@ -77,7 +77,7 @@ X11_CreateDefaultCursor()
cursor = SDL_calloc(1, sizeof(*cursor));
if (cursor) {
/* None is used to indicate the default cursor */
cursor->driverdata = (void*)None;
cursor->driverdata = (void*)(uintptr_t)None;
} else {
SDL_OutOfMemory();
}
@@ -216,7 +216,7 @@ X11_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
if (x11_cursor == None) {
x11_cursor = X11_CreatePixmapCursor(surface, hot_x, hot_y);
}
cursor->driverdata = (void*)x11_cursor;
cursor->driverdata = (void*)(uintptr_t)x11_cursor;
} else {
SDL_OutOfMemory();
}
@@ -257,7 +257,7 @@ X11_CreateSystemCursor(SDL_SystemCursor id)
x11_cursor = X11_XCreateFontCursor(GetDisplay(), shape);
cursor->driverdata = (void*)x11_cursor;
cursor->driverdata = (void*)(uintptr_t)x11_cursor;
} else {
SDL_OutOfMemory();
}

View File

@@ -1,6 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 2021 NVIDIA Corporation
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -420,6 +421,9 @@ X11_GL_InitExtensions(_THIS)
_this->gl_data->glXChooseFBConfig =
(GLXFBConfig *(*)(Display *, int, const int *, int *))
X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
_this->gl_data->glXGetVisualFromFBConfig =
(XVisualInfo *(*)(Display *, GLXFBConfig))
X11_GL_GetProcAddress(_this, "glXGetVisualFromFBConfig");
}
/* Check for GLX_EXT_visual_rating */
@@ -598,7 +602,7 @@ X11_GL_GetVisual(_THIS, Display * display, int screen)
{
/* 64 seems nice. */
int attribs[64];
XVisualInfo *vinfo;
XVisualInfo *vinfo = NULL;
int *pvistypeattr = NULL;
if (!_this->gl_data) {
@@ -606,12 +610,33 @@ X11_GL_GetVisual(_THIS, Display * display, int screen)
return NULL;
}
X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr);
vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
if (_this->gl_data->glXChooseFBConfig &&
_this->gl_data->glXGetVisualFromFBConfig) {
GLXFBConfig *framebuffer_config = NULL;
int fbcount = 0;
if (!vinfo && (pvistypeattr != NULL)) {
*pvistypeattr = None;
X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_TRUE, &pvistypeattr);
framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
if (!framebuffer_config && (pvistypeattr != NULL)) {
*pvistypeattr = None;
framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount);
}
if (framebuffer_config) {
vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[0]);
}
X11_XFree(framebuffer_config);
}
if (!vinfo) {
X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr);
vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
if (!vinfo && (pvistypeattr != NULL)) {
*pvistypeattr = None;
vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
}
}
if (!vinfo) {

View File

@@ -53,6 +53,7 @@ struct SDL_GLDriverData
GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
XVisualInfo *(*glXGetVisualFromFBConfig) (Display*,GLXFBConfig);
void (*glXDestroyContext) (Display*, GLXContext);
Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
void (*glXSwapBuffers) (Display*, GLXDrawable);

View File

@@ -119,8 +119,9 @@ SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d)
SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return)
SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),)
SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return)
SDL_X11_SYM(void,XSetWMProperties,(Display* a,Window b,XTextProperty* c,XTextProperty* d,char** e,int f,XSizeHints* g,XWMHints* h,XClassHint* i),(a,b,c,d,e,f,g,h,i),)
SDL_X11_SYM(void,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),)
SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
SDL_X11_SYM(void,XSetWMProperties,(Display* a,Window b,XTextProperty* c,XTextProperty* d,char** e,int f,XSizeHints* g,XWMHints* h,XClassHint* i),(a,b,c,d,e,f,g,h,i),)
SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
SDL_X11_SYM(int,XStoreName,(Display* a,Window b,_Xconst char* c),(a,b,c),return)

View File

@@ -453,10 +453,6 @@ X11_VideoInit(_THIS)
X11_InitTouch(_this);
#if SDL_USE_LIBDBUS
SDL_DBus_Init();
#endif
return 0;
}

View File

@@ -734,7 +734,7 @@ X11_SetWindowTitle(_THIS, SDL_Window * window)
status = X11_XChangeProperty(display, data->xwindow, _NET_WM_NAME, UTF8_STRING, 8, 0, (const unsigned char *) title, strlen(title));
if (status != Success) {
if (status != 1) {
char *x11_error = NULL;
char x11_error_locale[256];
if (X11_XGetErrorText(display, status, x11_error_locale, sizeof(x11_error_locale)) == Success)
@@ -1749,26 +1749,48 @@ X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
}
int
X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count)
X11_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
XWMHints *wmhints;
Atom demands_attention = X11_XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 1);
Atom wm_state = X11_XInternAtom(display, "_NET_WM_STATE", 1);
wmhints = X11_XGetWMHints(display, data->xwindow);
if (!wmhints) {
return SDL_SetError("Couldn't get WM hints");
}
XEvent snd_ntfy_ev = {ClientMessage};
snd_ntfy_ev.xclient.window = data->xwindow;
snd_ntfy_ev.xclient.message_type = wm_state;
snd_ntfy_ev.xclient.format = 32;
snd_ntfy_ev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD */
snd_ntfy_ev.xclient.data.l[1] = demands_attention;
snd_ntfy_ev.xclient.data.l[2] = 0;
snd_ntfy_ev.xclient.data.l[3] = 1; /* normal application */
snd_ntfy_ev.xclient.data.l[4] = 0;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &snd_ntfy_ev);
wmhints->flags &= ~XUrgencyHint;
data->flashing_window = SDL_FALSE;
data->flash_cancel_time = 0;
switch (operation) {
case SDL_FLASH_CANCEL:
/* Taken care of above */
break;
case SDL_FLASH_BRIEFLY:
if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
wmhints->flags |= XUrgencyHint;
data->flashing_window = SDL_TRUE;
/* On Ubuntu 21.04 this causes a dialog to pop up, so leave it up for a full second so users can see it */
data->flash_cancel_time = SDL_GetTicks() + 1000;
if (!data->flash_cancel_time) {
data->flash_cancel_time = 1;
}
}
break;
case SDL_FLASH_UNTIL_FOCUSED:
if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
wmhints->flags |= XUrgencyHint;
data->flashing_window = SDL_TRUE;
}
break;
default:
break;
}
X11_XSetWMHints(display, data->xwindow, wmhints);
X11_XFree(wmhints);
return 0;
}

View File

@@ -68,6 +68,8 @@ typedef struct
unsigned long user_time;
Atom xdnd_req;
Window xdnd_source;
SDL_bool flashing_window;
Uint32 flash_cancel_time;
#if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
@@ -107,7 +109,7 @@ extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
extern int X11_FlashWindow(_THIS, SDL_Window * window, SDL_FlashOperation operation);
#endif /* SDL_x11window_h_ */