Skip to content

Commit 10df83d

Browse files
authored
Merge pull request #3470 from pygame-community/ankith26-windowevent-fix
Fix windowevent and key repeat in sdl2-compat
2 parents 2a3fa66 + 36e0989 commit 10df83d

File tree

2 files changed

+46
-25
lines changed

2 files changed

+46
-25
lines changed

src_c/_pygame.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,6 @@ typedef enum {
439439

440440
PGE_MIDIIN,
441441
PGE_MIDIOUT,
442-
PGE_KEYREPEAT, /* Special internal pygame event, for managing key-presses
443-
*/
444442

445443
/* DO NOT CHANGE THE ORDER OF EVENTS HERE */
446444
PGE_WINDOWSHOWN,

src_c/event.c

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,21 @@ _pg_repeat_callback(Uint32 interval, void *param)
152152
int repeat_interval_copy = pg_key_repeat_interval;
153153
PG_UNLOCK_EVFILTER_MUTEX
154154

155-
repeat_event_copy.type = PGE_KEYREPEAT;
155+
repeat_event_copy.type = SDL_KEYDOWN;
156156
#if SDL_VERSION_ATLEAST(3, 0, 0)
157157
repeat_event_copy.key.down = true;
158158
repeat_event_copy.key.repeat = true;
159159
#else
160160
repeat_event_copy.key.state = SDL_PRESSED;
161161
repeat_event_copy.key.repeat = 1;
162162
#endif
163-
SDL_PushEvent(&repeat_event_copy);
163+
/* Use SDL_PeepEvents and not SDL_PushEvent because we don't want
164+
* this to go through our event filter.
165+
* Because this doesn't go through our filter we have to check event
166+
* blocking beforehand. */
167+
if (PG_EventEnabled(_pg_pgevent_proxify(repeat_event_copy.type))) {
168+
SDL_PeepEvents(&repeat_event_copy, 1, SDL_ADDEVENT, 0, 0);
169+
}
164170
return repeat_interval_copy;
165171
}
166172

@@ -470,19 +476,40 @@ _pg_pgevent_deproxify(Uint32 type)
470476
return _pg_pgevent_proxify_helper(type, 0);
471477
}
472478

479+
/* Get type of an event, handling WINDOWEVENT translation on SDL2.
480+
* On SDL3 this function is trivial */
481+
static Uint32
482+
_pg_pgevent_type(SDL_Event *event)
483+
{
473484
#if !SDL_VERSION_ATLEAST(3, 0, 0)
474-
/* We don't need to do window event translation because in SDL3 each window
475-
* event is its own thing anyways */
476-
static int
477-
_pg_translate_windowevent(void *_, SDL_Event *event)
485+
if (event->type == SDL_WINDOWEVENT) {
486+
return PGE_WINDOWSHOWN + event->window.event - 1;
487+
}
488+
#endif
489+
return event->type;
490+
}
491+
492+
/* Handle blocking of pseudo-blocked events.
493+
* Currently this only includes WINDOWEVENT, but can be expanded in the
494+
* future.
495+
*/
496+
#if SDL_VERSION_ATLEAST(3, 0, 0)
497+
static bool SDLCALL
498+
#else
499+
static int SDLCALL
500+
#endif
501+
_pg_filter_blocked_events(void *_, SDL_Event *event)
478502
{
503+
#if SDL_VERSION_ATLEAST(3, 0, 0)
504+
if (event->type >= SDL_EVENT_WINDOW_FIRST &&
505+
event->type <= SDL_EVENT_WINDOW_LAST) {
506+
#else
479507
if (event->type == SDL_WINDOWEVENT) {
480-
event->type = PGE_WINDOWSHOWN + event->window.event - 1;
481-
return PG_EventEnabled(_pg_pgevent_proxify(event->type));
508+
#endif
509+
return PG_EventEnabled(_pg_pgevent_proxify(_pg_pgevent_type(event)));
482510
}
483511
return 1;
484512
}
485-
#endif
486513

487514
#if SDL_VERSION_ATLEAST(3, 0, 0)
488515
static bool SDLCALL
@@ -613,10 +640,6 @@ pg_event_filter(void *_, SDL_Event *event)
613640
PG_UNLOCK_EVFILTER_MUTEX
614641
}
615642

616-
else if (event->type == PGE_KEYREPEAT) {
617-
event->type = SDL_KEYDOWN;
618-
}
619-
620643
else if (event->type == SDL_KEYUP) {
621644
PG_LOCK_EVFILTER_MUTEX
622645
/* Actual keyup is blocked, so clear unneeded cache if it exists */
@@ -709,6 +732,14 @@ pg_event_filter(void *_, SDL_Event *event)
709732
return RAISE(pgExc_SDLError, SDL_GetError()), 0;
710733
*/
711734
}
735+
/* TODO:
736+
* Any event that gets blocked here will not be visible to the event
737+
* watchers. So things like WINDOWEVENT should never be blocked here.
738+
* This is taken care of in SDL2 codepaths already but needs to also
739+
* be verified in SDL3 porting.
740+
* If the user requests a block on WINDOWEVENTs we are going to handle
741+
* it specially and call it a "pseudo-block", where the filtering will
742+
* happen in a _pg_filter_blocked_events call. */
712743
return PG_EventEnabled(_pg_pgevent_proxify(event->type));
713744
}
714745

@@ -1747,6 +1778,7 @@ pgEvent_New(SDL_Event *event)
17471778
}
17481779

17491780
if (event) {
1781+
event->type = _pg_pgevent_type(event);
17501782
e->type = _pg_pgevent_deproxify(event->type);
17511783
e->dict = dict_from_event(event);
17521784
}
@@ -1846,14 +1878,7 @@ _pg_event_pump(int dopump)
18461878
SDL_PumpEvents();
18471879
}
18481880

1849-
/* WINDOWEVENT translation needed only on SDL2 */
1850-
#if !SDL_VERSION_ATLEAST(3, 0, 0)
1851-
/* We need to translate WINDOWEVENTS. But if we do that from the
1852-
* from event filter, internal SDL stuff that rely on WINDOWEVENT
1853-
* might break. So after every event pump, we translate events from
1854-
* here */
1855-
SDL_FilterEvents(_pg_translate_windowevent, NULL);
1856-
#endif
1881+
SDL_FilterEvents(_pg_filter_blocked_events, NULL);
18571882
}
18581883

18591884
static int
@@ -2458,8 +2483,6 @@ pg_event_set_blocked(PyObject *self, PyObject *obj)
24582483
/* Never block SDL_WINDOWEVENT on SDL2, we need them for translation */
24592484
PG_SetEventEnabled(SDL_WINDOWEVENT, SDL_TRUE);
24602485
#endif
2461-
/* Never block PGE_KEYREPEAT too, its needed for pygame internal use */
2462-
PG_SetEventEnabled(PGE_KEYREPEAT, SDL_TRUE);
24632486
Py_RETURN_NONE;
24642487
}
24652488

0 commit comments

Comments
 (0)