X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
Clip rectangle set to int(left+width/2) , int(top+height/2) , int(left+width/2)+1 , int(top+height/2)+1
a 1x1 box
On even-valued resolution, cursor is stable at bottom-right central pixel
On odd-valued resolution, cursor is stable at exact central pixel.
this is the desired behaviour
In some cases, a backbuffer size update may not be accompanied by a resize event if the window size and/or scale were updated before the new backbuffer size was recomputed. Instead of the scale, use the old/new backbuffer sizes to determine if a resize event is required so that a backbuffer size change will always be followed by a resize event.
Instead of wrapping individual calls to SDL_SetDisplayModeForDisplay(), just check the flag in the function itself and make it a NOP that cannot fail if the flag is set. Silences some errant "SDL video driver doesn't support changing display mode" log errors.
When hiding a window, libdecor can report bogus content region sizes that are +/- the height of the title bar. Ignore any size values from libdecor when hiding a window, or the size may be incorrect when restored.
The compositor can arbitrarily move windows between displays, including fullscreen windows. Update the internal state when a fullscreen window is moved so the internal SDL state accurately reflects the window location, and resize the window to fit the new display.
This also fixes an edge case where the compositor can make a window fullscreen on a different display than SDL thinks it will be on (usually when a window is made fullscreen by the compositor while straddling multiple displays), which can result in the window being incorrectly sized.
If additional fullscreen requests are received when the window is already fullscreen, it is typically due to the fullscreen flags or emulated video mode being changed. A commit must be explicitly triggered or the requested changes won't take effect until some other event, such as a resize or focus change, causes the changes to be committed.
The compositor can toggle the fullscreen state (via a hotkey or otherwise), so the internal SDL state must be updated accordingly when it does.
When toggling fullscreen via the compositor, SDL will attempt to use the last fullscreen flag explicitly set. If no flag was previously set, SDL_WINDOW_FULLSCREEN will be used if a window video mode was set, otherwise SDL_WINDOW_FULLSCREEN_DESKTOP will be used. If the previous flag was SDL_WINDOW_FULLSCREEN and the window video mode was cleared, it will revert to SDL_WINDOW_FULLSCREEN_DESKTOP.
Adjust candidate count so list is not draw bigger that needed. This also fix potential uninitialised read of variable `candsize[i]` if `vertical` is false.
Update the Wayland core protocol spec file and add support for the new axis_value120 event to handle high resolution scroll wheels.
The axis_value120 replaces the axis_discrete event, which is no longer sent as of version 8 of the protocol. Note that unlike the axis_discrete event, no mention in the spec is made regarding how many axis_value120 events may occur per-axis per-frame, so the values are accumulated and committed when the pointer frame event occurs.
The libdecor header internally includes wayland-client.h, which pulls in the wayland-client-protocol.h file from the system include path and overrides the local one generated from the included Wayland protocol spec files. Move the Wayland protocol header inclusion above the libdecor header inclusion to ensure that the locally generated protocol header is used instead.
When minimizing a window, we get this sequence of events:
WM_WINDOWPOSCHANGING
WM_GETMINMAXINFO
WM_NCCALCSIZE
WM_WINDOWPOSCHANGED - IsIconic() is true
WM_MOVE
WM_SIZE - SDL sees minimized state here
When restoring a window, we get this sequence of events:
WM_WINDOWPOSCHANGING
WM_GETMINMAXINFO
WM_NCCALCSIZE
WM_NCPAINT
WM_ERASEBKGND
WM_WINDOWPOSCHANGED - IsIconic() is false
WM_MOVE
WM_SIZE - SDL sees restored state here
On Windows 10 a minimized window has a non-empty client rect, so we were delivering a minimized size before SDL knows that the window is minimized, and then ignoring the restored size when handling the restore message.
The fix is to use IsIconic() which returns the correct window state when WM_WINDOWPOSCHANGED is actually delivered.
Uses VK_EXT_metal_surface (vkCreateMetalSurfaceEXT)
when possible, otherwise falls back to the obsoleted
VK_MVK_macos_surface and VK_MVK_ios_surface.
Fixes#3906
If libdecor performs a commit with the frame title being undefined, a crash can occur within the library or its plugins. Always ensure that the title is set to a valid string to avoid this.
Eliminate excessive calls to SetFullscreen by removing the calls in the libdecor and xdg-toplevel config callbacks.
These calls were being made there in case something explicitly called the window minimization function from within SDL, which unsets fullscreen, and as minimizing a window in Wayland is just a suggestion to the compositor and doesn't actually change the window state or communicate anything back to the application, it was necessary to call SetFullscreen in every call to the config functions just in case something minimized a window via SDL_MinimizeWindow() and later needed to restore it. GNOME in particular had issues when fullscreen set/unset operations were being hammered, leading to overlapping acks and commits when switching to fullscreen.
With the new video system flag to disable unsetting fullscreen when minimizing a window, these calls in the configuration functions are no longer needed and can be removed. This significantly reduces calls to the SetFullscreen() function, reverts #6044 while fixing the issue, and fixes a similar problem when hiding and showing a window initially created with fullscreen flags.