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"
|
|
|
|
|
2017-08-28 00:22:23 -07:00
|
|
|
#ifndef SDL_waylandevents_h_
|
|
|
|
#define SDL_waylandevents_h_
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
#include "SDL_waylandvideo.h"
|
|
|
|
#include "SDL_waylandwindow.h"
|
2016-11-06 08:34:27 -08:00
|
|
|
#include "SDL_waylanddatamanager.h"
|
2021-07-29 10:27:31 -07:00
|
|
|
#include "SDL_waylandkeyboard.h"
|
2016-11-06 08:34:27 -08:00
|
|
|
|
2022-07-15 10:44:49 -07:00
|
|
|
enum SDL_WaylandAxisEvent
|
|
|
|
{
|
|
|
|
AXIS_EVENT_CONTINUOUS = 0,
|
|
|
|
AXIS_EVENT_DISCRETE,
|
|
|
|
AXIS_EVENT_VALUE120
|
|
|
|
};
|
|
|
|
|
2022-03-23 10:46:25 -07:00
|
|
|
struct SDL_WaylandTabletSeat;
|
|
|
|
|
|
|
|
struct SDL_WaylandTabletObjectListNode {
|
|
|
|
void* object;
|
|
|
|
struct SDL_WaylandTabletObjectListNode* next;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SDL_WaylandTabletInput {
|
|
|
|
struct SDL_WaylandTabletSeat* seat;
|
|
|
|
|
|
|
|
struct SDL_WaylandTabletObjectListNode* tablets;
|
|
|
|
struct SDL_WaylandTabletObjectListNode* tools;
|
|
|
|
struct SDL_WaylandTabletObjectListNode* pads;
|
|
|
|
|
|
|
|
SDL_WindowData *tool_focus;
|
|
|
|
uint32_t tool_prox_serial;
|
|
|
|
|
|
|
|
/* Last motion location */
|
|
|
|
wl_fixed_t sx_w;
|
|
|
|
wl_fixed_t sy_w;
|
|
|
|
|
|
|
|
SDL_bool is_down;
|
|
|
|
|
|
|
|
SDL_bool btn_stylus;
|
|
|
|
SDL_bool btn_stylus2;
|
|
|
|
SDL_bool btn_stylus3;
|
|
|
|
};
|
|
|
|
|
2021-02-25 17:30:47 -08:00
|
|
|
typedef struct {
|
|
|
|
// repeat_rate in range of [1, 1000]
|
|
|
|
int32_t repeat_rate;
|
|
|
|
int32_t repeat_delay;
|
|
|
|
SDL_bool is_initialized;
|
|
|
|
|
|
|
|
SDL_bool is_key_down;
|
wayland: Avoid spurious key repeats when not pumping events
Previous to this commit, key repeats events were typically generated when
pumping events, based on the time of when the events are pumped. However,
if an application doesn't call `SDL_PumpEvents` for some seconds, this time
can be multiple seconds in the future compared to the actual key up event time,
and generates key repeats even if a key was pressed only for an instant.
In practice, this can happen when the user presses a key which causes the
application to do something without pumping events (e.g. load a level).
In Crispy Doom & PrBoom+, when the user presses the key bound to "Restart
level/demo", the game doesn't pump events during the "screen melt" effect,
and the level is restarted multiple times due to spurious repeats.
To fix this, if the key up event is among the events to be pumped, we generate
the key repeats there, since in the Wayland callback we receive the time when
the key up event happened. Otherwise, we know no key up event happened and we
can generate as many repeats as necessary after pumping.
Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com>
2022-01-08 10:24:47 -08:00
|
|
|
uint32_t wl_press_time; // Key press time as reported by the Wayland API
|
2022-01-08 10:09:35 -08:00
|
|
|
uint32_t sdl_press_time; // Key press time expressed in SDL ticks
|
2021-02-25 17:30:47 -08:00
|
|
|
uint32_t next_repeat_ms;
|
|
|
|
uint32_t scancode;
|
|
|
|
char text[8];
|
|
|
|
} SDL_WaylandKeyboardRepeat;
|
|
|
|
|
|
|
|
struct SDL_WaylandInput {
|
|
|
|
SDL_VideoData *display;
|
|
|
|
struct wl_seat *seat;
|
|
|
|
struct wl_pointer *pointer;
|
|
|
|
struct wl_touch *touch;
|
|
|
|
struct wl_keyboard *keyboard;
|
|
|
|
SDL_WaylandDataDevice *data_device;
|
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
|
|
|
SDL_WaylandPrimarySelectionDevice *primary_selection_device;
|
2021-07-29 10:27:31 -07:00
|
|
|
SDL_WaylandTextInput *text_input;
|
2021-02-25 17:30:47 -08:00
|
|
|
struct zwp_relative_pointer_v1 *relative_pointer;
|
|
|
|
SDL_WindowData *pointer_focus;
|
|
|
|
SDL_WindowData *keyboard_focus;
|
|
|
|
uint32_t pointer_enter_serial;
|
|
|
|
|
|
|
|
/* Last motion location */
|
|
|
|
wl_fixed_t sx_w;
|
|
|
|
wl_fixed_t sy_w;
|
|
|
|
|
2022-08-06 06:19:52 -07:00
|
|
|
uint32_t buttons_pressed;
|
|
|
|
|
2021-02-25 17:30:47 -08:00
|
|
|
double dx_frac;
|
|
|
|
double dy_frac;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct xkb_keymap *keymap;
|
|
|
|
struct xkb_state *state;
|
2021-04-13 16:56:50 -07:00
|
|
|
struct xkb_compose_table *compose_table;
|
|
|
|
struct xkb_compose_state *compose_state;
|
2022-03-25 09:51:38 -07:00
|
|
|
|
|
|
|
/* Keyboard layout "group" */
|
|
|
|
uint32_t current_group;
|
|
|
|
|
|
|
|
/* Modifier bitshift values */
|
|
|
|
uint32_t idx_shift;
|
|
|
|
uint32_t idx_ctrl;
|
|
|
|
uint32_t idx_alt;
|
|
|
|
uint32_t idx_gui;
|
|
|
|
uint32_t idx_num;
|
|
|
|
uint32_t idx_caps;
|
2021-02-25 17:30:47 -08:00
|
|
|
} xkb;
|
|
|
|
|
|
|
|
/* information about axis events on current frame */
|
|
|
|
struct {
|
2022-07-15 10:44:49 -07:00
|
|
|
enum SDL_WaylandAxisEvent x_axis_type;
|
2021-02-25 17:30:47 -08:00
|
|
|
float x;
|
|
|
|
|
2022-07-15 10:44:49 -07:00
|
|
|
enum SDL_WaylandAxisEvent y_axis_type;
|
2021-02-25 17:30:47 -08:00
|
|
|
float y;
|
|
|
|
} pointer_curr_axis_info;
|
|
|
|
|
|
|
|
SDL_WaylandKeyboardRepeat keyboard_repeat;
|
2022-03-23 10:46:25 -07:00
|
|
|
|
|
|
|
struct SDL_WaylandTabletInput* tablet;
|
2021-02-25 17:30:47 -08:00
|
|
|
};
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
extern void Wayland_PumpEvents(_THIS);
|
2021-10-24 19:28:04 -07:00
|
|
|
extern void Wayland_SendWakeupEvent(_THIS, SDL_Window *window);
|
|
|
|
extern int Wayland_WaitEventTimeout(_THIS, int timeout);
|
2015-06-21 08:33:46 -07:00
|
|
|
|
2021-04-08 11:08:35 -07:00
|
|
|
extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
|
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
|
|
|
extern void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
|
2021-07-29 10:27:31 -07:00
|
|
|
extern void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
|
2021-04-08 11:08:35 -07:00
|
|
|
|
2020-04-07 10:30:46 -07:00
|
|
|
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version);
|
2015-06-21 08:33:46 -07:00
|
|
|
extern void Wayland_display_destroy_input(SDL_VideoData *d);
|
|
|
|
|
2016-09-01 01:26:56 -07:00
|
|
|
extern void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id);
|
|
|
|
extern void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d);
|
|
|
|
|
|
|
|
extern int Wayland_input_lock_pointer(struct SDL_WaylandInput *input);
|
|
|
|
extern int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input);
|
|
|
|
|
2021-11-08 22:30:00 -08:00
|
|
|
extern int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *window);
|
|
|
|
extern int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input, SDL_Window *window);
|
2020-04-17 10:55:44 -07:00
|
|
|
|
2016-09-01 01:26:56 -07:00
|
|
|
extern void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id);
|
|
|
|
extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d);
|
|
|
|
|
2021-01-19 16:20:07 -08:00
|
|
|
extern int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input);
|
|
|
|
extern int Wayland_input_ungrab_keyboard(SDL_Window *window);
|
|
|
|
|
2022-03-23 10:46:25 -07:00
|
|
|
extern void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager* tablet_manager);
|
|
|
|
extern void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input);
|
|
|
|
|
2017-08-28 00:22:23 -07:00
|
|
|
#endif /* SDL_waylandevents_h_ */
|
2015-06-21 08:33:46 -07:00
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|