2015-06-21 08:33:46 -07:00
|
|
|
/*
|
|
|
|
Simple DirectMedia Layer
|
2022-01-03 09:40:00 -08:00
|
|
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "../../SDL_internal.h"
|
2021-02-01 08:57:39 -08:00
|
|
|
#include "SDL_stdinc.h"
|
2015-06-21 08:33:46 -07:00
|
|
|
|
2017-08-28 00:22:23 -07:00
|
|
|
#ifndef SDL_waylandvideo_h_
|
|
|
|
#define SDL_waylandvideo_h_
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
#include <EGL/egl.h>
|
|
|
|
#include "wayland-util.h"
|
|
|
|
|
wayland: Implement basic window move events via wl_surface_listener.
This unearthed an unspeakably large amount of bugs in the wl_output enumerator,
notably the fact that the wl_output user pointer was to temporary memory!
This was "fixed" in e862856, and was then pointed out as a leak in 4183211,
which was undone in d9ba204. The busted fix was correct that the malloc was an
issue, but wrong about _why_; SDL_AddVideoDisplay copies by value and does not
reuse the pointer, so generally you want your VideoDisplay to be on the stack,
but of course the callbacks don't allow that, so a malloc was a workaround. But
we can do better and just host our temporary display inside WaylandOutputData
because that will be persistent while also not leaking.
Wait, wasn't I talking about move events? Right, that: wl_surface_listener does
at least give us the ability to know what monitor we're on, even though we have
no idea where we are on the monitor. All we need to do is check the wl_output
against the display list and then push a move event that both indicates the
correct display while also not being _too_ much of a lie (but enough of a lie
to where our event doesn't get discarded as "undefined" or whatever). The index
check for the video display is what spawned the great nightmare you see before
you; aside from the bugfix this is actually a really basic patch.
2021-04-16 18:35:50 -07:00
|
|
|
#include "../SDL_sysvideo.h"
|
2021-08-08 21:27:08 -07:00
|
|
|
#include "../../core/linux/SDL_dbus.h"
|
2021-03-29 13:57:03 -07:00
|
|
|
#include "../../core/linux/SDL_ime.h"
|
2021-01-20 19:17:20 -08:00
|
|
|
|
2015-06-21 08:33:46 -07:00
|
|
|
struct xkb_context;
|
|
|
|
struct SDL_WaylandInput;
|
2022-03-23 10:46:25 -07:00
|
|
|
struct SDL_WaylandTabletManager;
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
|
|
|
struct SDL_WaylandTouch;
|
|
|
|
struct qt_surface_extension;
|
|
|
|
struct qt_windowmanager;
|
|
|
|
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
|
|
|
|
2021-09-22 10:26:44 -07:00
|
|
|
typedef struct {
|
|
|
|
struct wl_cursor_theme *theme;
|
|
|
|
int size;
|
|
|
|
} SDL_WaylandCursorTheme;
|
|
|
|
|
2022-03-24 12:32:25 -07:00
|
|
|
typedef struct SDL_WaylandOutputData SDL_WaylandOutputData;
|
|
|
|
|
2015-06-21 08:33:46 -07:00
|
|
|
typedef struct {
|
2021-11-23 12:14:18 -08:00
|
|
|
SDL_bool initializing;
|
2015-06-21 08:33:46 -07:00
|
|
|
struct wl_display *display;
|
Fixed bug 4689 - SDL fails to detect compositor shutdown on Wayland -- program keeps running
M Stoeckl
To reproduce:
1. Run any SDL-based program with a Wayland compositor, orphaning it so that it doesn't have an immediate parent process. (For example, from a terminal, running `supertux2 & disown`.) The program should use the wayland backend, i.e. by setting environment variable SDL_VIDEODRIVER=wayland.
2. Kill the compositor process.
Results:
- The SDL program will keep running.
Expected results:
- The SDL program should close. (What close should mean here, I'm not sure - is injecting an SDL_Quit the appropriate action when a video driver disconnects?)
Build data:
2019-06-22, hg tip (12901:bf8d9d29cbf1), Linux, can reproduce with sway, weston, and other Wayland oompositors.
2019-08-05 23:38:48 -07:00
|
|
|
int display_disconnected;
|
2015-06-21 08:33:46 -07:00
|
|
|
struct wl_registry *registry;
|
|
|
|
struct wl_compositor *compositor;
|
|
|
|
struct wl_shm *shm;
|
2021-09-22 10:26:44 -07:00
|
|
|
SDL_WaylandCursorTheme *cursor_themes;
|
|
|
|
int num_cursor_themes;
|
2015-06-21 08:33:46 -07:00
|
|
|
struct wl_pointer *pointer;
|
2018-02-07 10:13:55 -08:00
|
|
|
struct {
|
2018-06-24 22:42:36 -07:00
|
|
|
struct xdg_wm_base *xdg;
|
2020-06-11 14:10:28 -07:00
|
|
|
#ifdef HAVE_LIBDECOR_H
|
|
|
|
struct libdecor *libdecor;
|
|
|
|
#endif
|
2018-02-07 10:13:55 -08:00
|
|
|
} shell;
|
2016-09-01 01:26:56 -07:00
|
|
|
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
|
|
|
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
2016-11-06 08:34:27 -08:00
|
|
|
struct wl_data_device_manager *data_device_manager;
|
Add support for X11 primary selection (#6132)
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>`
2022-09-14 09:28:35 -07:00
|
|
|
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
2018-11-04 12:08:40 -08:00
|
|
|
struct zxdg_decoration_manager_v1 *decoration_manager;
|
2021-01-19 16:20:07 -08:00
|
|
|
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager;
|
2021-01-20 19:17:20 -08:00
|
|
|
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
2021-06-02 08:41:44 -07:00
|
|
|
struct xdg_activation_v1 *activation_manager;
|
2021-07-29 10:27:31 -07:00
|
|
|
struct zwp_text_input_manager_v3 *text_input_manager;
|
2022-03-19 12:58:47 -07:00
|
|
|
struct zxdg_output_manager_v1 *xdg_output_manager;
|
2022-03-25 17:35:07 -07:00
|
|
|
struct wp_viewporter *viewporter;
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
EGLDisplay edpy;
|
|
|
|
EGLContext context;
|
|
|
|
EGLConfig econf;
|
|
|
|
|
|
|
|
struct xkb_context *xkb_context;
|
|
|
|
struct SDL_WaylandInput *input;
|
2022-03-23 10:46:25 -07:00
|
|
|
struct SDL_WaylandTabletManager *tablet_manager;
|
2022-03-24 12:32:25 -07:00
|
|
|
SDL_WaylandOutputData *output_list;
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
|
|
|
struct SDL_WaylandTouch *touch;
|
|
|
|
struct qt_surface_extension *surface_extension;
|
|
|
|
struct qt_windowmanager *windowmanager;
|
|
|
|
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
|
2016-09-01 01:22:58 -07:00
|
|
|
|
|
|
|
char *classname;
|
2016-09-01 01:26:56 -07:00
|
|
|
|
|
|
|
int relative_mouse_mode;
|
2015-06-21 08:33:46 -07:00
|
|
|
} SDL_VideoData;
|
|
|
|
|
2022-03-24 12:32:25 -07:00
|
|
|
struct SDL_WaylandOutputData {
|
2021-11-23 12:14:18 -08:00
|
|
|
SDL_VideoData *videodata;
|
2019-06-11 15:55:05 -07:00
|
|
|
struct wl_output *output;
|
2022-03-19 12:58:47 -07:00
|
|
|
struct zxdg_output_v1 *xdg_output;
|
2021-11-17 21:43:55 -08:00
|
|
|
uint32_t registry_id;
|
2019-06-11 15:55:05 -07:00
|
|
|
float scale_factor;
|
2022-03-25 17:35:07 -07:00
|
|
|
int native_width, native_height;
|
2021-04-18 06:33:06 -07:00
|
|
|
int x, y, width, height, refresh, transform;
|
2021-11-15 08:52:43 -08:00
|
|
|
SDL_DisplayOrientation orientation;
|
2021-04-18 19:26:27 -07:00
|
|
|
int physical_width, physical_height;
|
|
|
|
float ddpi, hdpi, vdpi;
|
2022-03-26 16:55:04 -07:00
|
|
|
SDL_bool has_logical_position, has_logical_size;
|
2021-11-15 08:52:43 -08:00
|
|
|
int index;
|
wayland: Implement basic window move events via wl_surface_listener.
This unearthed an unspeakably large amount of bugs in the wl_output enumerator,
notably the fact that the wl_output user pointer was to temporary memory!
This was "fixed" in e862856, and was then pointed out as a leak in 4183211,
which was undone in d9ba204. The busted fix was correct that the malloc was an
issue, but wrong about _why_; SDL_AddVideoDisplay copies by value and does not
reuse the pointer, so generally you want your VideoDisplay to be on the stack,
but of course the callbacks don't allow that, so a malloc was a workaround. But
we can do better and just host our temporary display inside WaylandOutputData
because that will be persistent while also not leaking.
Wait, wasn't I talking about move events? Right, that: wl_surface_listener does
at least give us the ability to know what monitor we're on, even though we have
no idea where we are on the monitor. All we need to do is check the wl_output
against the display list and then push a move event that both indicates the
correct display while also not being _too_ much of a lie (but enough of a lie
to where our event doesn't get discarded as "undefined" or whatever). The index
check for the video display is what spawned the great nightmare you see before
you; aside from the bugfix this is actually a really basic patch.
2021-04-16 18:35:50 -07:00
|
|
|
SDL_VideoDisplay placeholder;
|
2022-03-19 12:58:47 -07:00
|
|
|
int wl_output_done_count;
|
2022-03-24 12:32:25 -07:00
|
|
|
SDL_WaylandOutputData *next;
|
|
|
|
};
|
2019-06-11 15:55:05 -07:00
|
|
|
|
2021-08-03 10:30:57 -07:00
|
|
|
/* Needed here to get wl_surface declaration, fixes GitHub#4594 */
|
2021-08-03 10:17:19 -07:00
|
|
|
#include "SDL_waylanddyn.h"
|
|
|
|
|
2021-07-27 15:35:00 -07:00
|
|
|
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);
|
|
|
|
|
2022-05-11 13:04:34 -07:00
|
|
|
extern SDL_bool Wayland_LoadLibdecor(SDL_VideoData *data, SDL_bool ignore_xdg);
|
|
|
|
|
2017-08-28 00:22:23 -07:00
|
|
|
#endif /* SDL_waylandvideo_h_ */
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|