Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-06-30 15:53:31 +0300
committerCampbell Barton <campbell@blender.org>2022-06-30 16:46:57 +0300
commitcfd087673dfc74c411d5aeadc8b8c61ce1b05b9f (patch)
tree72dad7458af594d44abbee0abfff735486100007 /intern
parent1cf64434ed1aa2a3be65c73c61e030745a597858 (diff)
Fix key/dnd event handling accessing freed memory under Wayland
Closing a window could leave danging pointers which Wayland callbacks are responsible for clearing. However, any calls Blender makes that don't originate from Wayland's handlers don't have that assurance (key-repeat in this case). Resolve by using a window lookup on each key-repeat event.
Diffstat (limited to 'intern')
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp39
1 files changed, 22 insertions, 17 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index cec06ed6a50..6665a962e81 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -173,9 +173,15 @@ struct data_source_t {
char *buffer_out = nullptr;
};
+/**
+ * Data used to implement client-side key-repeat.
+ *
+ * \note it's important not to store the target window here
+ * as it can be closed while the key is repeating,
+ * instead use the focused keyboard from #intput_t which is cleared when windows are closed.
+ * Therefor keyboard events must always check the window has not been cleared.
+ */
struct key_repeat_payload_t {
- GHOST_SystemWayland *system = nullptr;
- GHOST_IWindow *window = nullptr;
struct input_t *input = nullptr;
xkb_keycode_t key_code;
@@ -803,8 +809,7 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event)
{
/* NOTE: `input->data_offer_dnd_mutex` must already be locked. */
const uint64_t time = input->system->getMilliSeconds();
- GHOST_WindowWayland *const win = static_cast<GHOST_WindowWayland *>(
- wl_surface_get_user_data(input->focus_dnd));
+ GHOST_WindowWayland *const win = window_from_surface(input->focus_dnd);
if (!win) {
return;
}
@@ -2027,8 +2032,6 @@ static void keyboard_handle_key(void *data,
if ((input->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) &&
xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key_code)) {
key_repeat_payload = new key_repeat_payload_t({
- .system = input->system,
- .window = win,
.input = input,
.key_code = key_code,
.key_data = {.gkey = gkey},
@@ -2042,17 +2045,19 @@ static void keyboard_handle_key(void *data,
task->getUserData());
input_t *input = payload->input;
- /* Calculate this value every time in case modifier keys are pressed. */
- char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
- xkb_state_key_get_utf8(input->xkb_state, payload->key_code, utf8_buf, sizeof(utf8_buf));
-
- payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(),
- GHOST_kEventKeyDown,
- payload->window,
- payload->key_data.gkey,
- '\0',
- utf8_buf,
- true));
+ if (GHOST_IWindow *win = window_from_surface(input->keyboard.wl_surface)) {
+ GHOST_SystemWayland *system = input->system;
+ /* Calculate this value every time in case modifier keys are pressed. */
+ char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
+ xkb_state_key_get_utf8(input->xkb_state, payload->key_code, utf8_buf, sizeof(utf8_buf));
+ system->pushEvent(new GHOST_EventKey(system->getMilliSeconds(),
+ GHOST_kEventKeyDown,
+ win,
+ payload->key_data.gkey,
+ '\0',
+ utf8_buf,
+ true));
+ }
};
input->key_repeat.timer = input->system->installTimer(
input->key_repeat.delay, 1000 / input->key_repeat.rate, key_repeat_fn, key_repeat_payload);