From 93828b93d3e657937d6ae582ae6a5b8a2cf432ae Mon Sep 17 00:00:00 2001 From: gresm <78505251+gresm@users.noreply.github.com> Date: Mon, 17 Jun 2024 19:58:42 +0200 Subject: [PATCH 01/13] Just rename "event.c" to "_event.c". --- buildconfig/Setup.Android.SDL2.in | 2 +- buildconfig/Setup.Emscripten.SDL2.in | 2 +- buildconfig/Setup.SDL2.in | 2 +- src_c/{event.c => _event.c} | 8 ++++---- src_c/display.c | 4 ++-- src_c/include/_pygame.h | 28 +++++++++++++++------------- src_c/meson.build | 6 +++--- src_c/static.c | 6 +++--- src_py/event.py | 1 + src_py/meson.build | 1 + 10 files changed, 32 insertions(+), 28 deletions(-) rename src_c/{event.c => _event.c} (99%) create mode 100644 src_py/event.py diff --git a/buildconfig/Setup.Android.SDL2.in b/buildconfig/Setup.Android.SDL2.in index fc556ad024..5ef285a55e 100644 --- a/buildconfig/Setup.Android.SDL2.in +++ b/buildconfig/Setup.Android.SDL2.in @@ -43,7 +43,7 @@ base src_c/base.c $(SDL) $(DEBUG) color src_c/color.c $(SDL) $(DEBUG) constants src_c/constants.c $(SDL) $(DEBUG) display src_c/display.c $(SDL) $(DEBUG) -event src_c/event.c $(SDL) $(DEBUG) +_event src_c/_event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) diff --git a/buildconfig/Setup.Emscripten.SDL2.in b/buildconfig/Setup.Emscripten.SDL2.in index 23b22f5766..2912b6d3a3 100644 --- a/buildconfig/Setup.Emscripten.SDL2.in +++ b/buildconfig/Setup.Emscripten.SDL2.in @@ -46,7 +46,7 @@ color src_c/void.c controller_old src_c/void.c display src_c/void.c draw src_c/void.c -event src_c/void.c +_event src_c/void.c font src_c/void.c gfxdraw src_c/void.c joystick src_c/void.c diff --git a/buildconfig/Setup.SDL2.in b/buildconfig/Setup.SDL2.in index 2fd66eeea3..e789e029f5 100644 --- a/buildconfig/Setup.SDL2.in +++ b/buildconfig/Setup.SDL2.in @@ -53,7 +53,7 @@ base src_c/base.c $(SDL) $(DEBUG) color src_c/color.c $(SDL) $(DEBUG) constants src_c/constants.c $(SDL) $(DEBUG) display src_c/display.c $(SDL) $(DEBUG) -event src_c/event.c $(SDL) $(DEBUG) +_event src_c/_event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) diff --git a/src_c/event.c b/src_c/_event.c similarity index 99% rename from src_c/event.c rename to src_c/_event.c index aa0c95b39e..68719fd7e8 100644 --- a/src_c/event.c +++ b/src_c/_event.c @@ -2241,9 +2241,9 @@ pg_event_custom_type(PyObject *self, PyObject *_null) } static PyMethodDef _event_methods[] = { - {"_internal_mod_init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, + {"init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, "auto initialize for event module"}, - {"_internal_mod_quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, + {"quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, "auto quit for event module"}, {"event_name", event_name, METH_VARARGS, DOC_EVENT_EVENTNAME}, @@ -2274,7 +2274,7 @@ static PyMethodDef _event_methods[] = { {NULL, NULL, 0, NULL}}; -MODINIT_DEFINE(event) +MODINIT_DEFINE(_event) { PyObject *module, *apiobj; static void *c_api[PYGAMEAPI_EVENT_NUMSLOTS]; @@ -2339,7 +2339,7 @@ MODINIT_DEFINE(event) c_api[8] = pgEvent_GetMouseButtonDownInfo; c_api[9] = pgEvent_GetMouseButtonUpInfo; - apiobj = encapsulate_api(c_api, "event"); + apiobj = encapsulate_api(c_api, "_event"); if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { Py_XDECREF(apiobj); Py_DECREF(module); diff --git a/src_c/display.c b/src_c/display.c index f677bce3e3..4002a57493 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -194,7 +194,7 @@ pg_display_quit(PyObject *self, PyObject *_null) pg_SetDefaultWindow(NULL); } - pg_mod_autoquit(IMPPREFIX "event"); + pg_mod_autoquit(IMPPREFIX "_event"); pg_mod_autoquit(IMPPREFIX "time"); pg_mod_autoquit(IMPPREFIX "window"); @@ -250,7 +250,7 @@ pg_display_init(PyObject *self, PyObject *_null) if (!pg_mod_autoinit(IMPPREFIX "time")) return NULL; - if (!pg_mod_autoinit(IMPPREFIX "event")) + if (!pg_mod_autoinit(IMPPREFIX "_event")) return NULL; if (!pg_mod_autoinit(IMPPREFIX "window")) return NULL; diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index 1477fe24cc..8851105083 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -388,34 +388,36 @@ typedef struct { typedef struct pgEventObject pgEventObject; #ifndef PYGAMEAPI_EVENT_INTERNAL -#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(event, 0)) +#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_event, 0)) #define pgEvent_Check(x) ((x)->ob_type == &pgEvent_Type) #define pgEvent_New \ - (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(event, 1)) + (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(_event, 1)) #define pg_post_event \ - (*(int (*)(Uint32, PyObject *))PYGAMEAPI_GET_SLOT(event, 2)) + (*(int (*)(Uint32, PyObject *))PYGAMEAPI_GET_SLOT(_event, 2)) #define pg_post_event_dictproxy \ - (*(int (*)(Uint32, pgEventDictProxy *))PYGAMEAPI_GET_SLOT(event, 3)) + (*(int (*)(Uint32, pgEventDictProxy *))PYGAMEAPI_GET_SLOT(_event, 3)) -#define pg_EnableKeyRepeat (*(int (*)(int, int))PYGAMEAPI_GET_SLOT(event, 4)) +#define pg_EnableKeyRepeat (*(int (*)(int, int))PYGAMEAPI_GET_SLOT(_event, 4)) -#define pg_GetKeyRepeat (*(void (*)(int *, int *))PYGAMEAPI_GET_SLOT(event, 5)) +#define pg_GetKeyRepeat \ + (*(void (*)(int *, int *))PYGAMEAPI_GET_SLOT(_event, 5)) -#define pgEvent_GetKeyDownInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 6)) +#define pgEvent_GetKeyDownInfo \ + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 6)) -#define pgEvent_GetKeyUpInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 7)) +#define pgEvent_GetKeyUpInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 7)) #define pgEvent_GetMouseButtonDownInfo \ - (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 8)) + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 8)) #define pgEvent_GetMouseButtonUpInfo \ - (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 9)) + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 9)) -#define import_pygame_event() IMPORT_PYGAME_MODULE(event) +#define import_pygame_event() IMPORT_PYGAME_MODULE(_event) #endif /* @@ -536,7 +538,7 @@ PYGAMEAPI_DEFINE_SLOTS(joystick); PYGAMEAPI_DEFINE_SLOTS(display); PYGAMEAPI_DEFINE_SLOTS(surface); PYGAMEAPI_DEFINE_SLOTS(surflock); -PYGAMEAPI_DEFINE_SLOTS(event); +PYGAMEAPI_DEFINE_SLOTS(_event); PYGAMEAPI_DEFINE_SLOTS(rwobject); PYGAMEAPI_DEFINE_SLOTS(pixelarray); PYGAMEAPI_DEFINE_SLOTS(color); @@ -550,7 +552,7 @@ PYGAMEAPI_EXTERN_SLOTS(joystick); PYGAMEAPI_EXTERN_SLOTS(display); PYGAMEAPI_EXTERN_SLOTS(surface); PYGAMEAPI_EXTERN_SLOTS(surflock); -PYGAMEAPI_EXTERN_SLOTS(event); +PYGAMEAPI_EXTERN_SLOTS(_event); PYGAMEAPI_EXTERN_SLOTS(rwobject); PYGAMEAPI_EXTERN_SLOTS(pixelarray); PYGAMEAPI_EXTERN_SLOTS(color); diff --git a/src_c/meson.build b/src_c/meson.build index 8e8287c834..2b8ff2e27d 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -35,9 +35,9 @@ display = py.extension_module( subdir: pg, ) -event = py.extension_module( - 'event', - 'event.c', +_event = py.extension_module( + '_event', + '_event.c', c_args: warnings_error, dependencies: pg_base_deps, install: true, diff --git a/src_c/static.c b/src_c/static.c index b7e8d1ec66..3042b58d44 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -115,7 +115,7 @@ PyInit_mouse(void); PyMODINIT_FUNC PyInit_key(void); PyMODINIT_FUNC -PyInit_event(void); +PyInit__event(void); PyMODINIT_FUNC PyInit_joystick(void); @@ -308,7 +308,7 @@ PyInit_pygame_static() load_submodule("pygame", PyInit_mask(), "mask"); load_submodule("pygame", PyInit_mouse(), "mouse"); - load_submodule("pygame", PyInit_event(), "event"); + load_submodule("pygame", PyInit__event(), "_event"); load_submodule("pygame", PyInit_joystick(), "joystick"); load_submodule("pygame", PyInit_pg_mixer(), "mixer"); @@ -393,7 +393,7 @@ PyInit_pygame_static() #include "joystick.c" -#include "event.c" +#include "_event.c" #include "mouse.c" diff --git a/src_py/event.py b/src_py/event.py new file mode 100644 index 0000000000..e1c5e04fd5 --- /dev/null +++ b/src_py/event.py @@ -0,0 +1 @@ +from pygame._event import * diff --git a/src_py/meson.build b/src_py/meson.build index 561aebaadb..28607b75a3 100644 --- a/src_py/meson.build +++ b/src_py/meson.build @@ -8,6 +8,7 @@ python_sources = files( 'camera.py', 'colordict.py', 'cursors.py', + 'event.py', 'freetype.py', 'ftfont.py', 'locals.py', From a604caa54142091f20762eed981b2af9057e8d89 Mon Sep 17 00:00:00 2001 From: gresm <78505251+gresm@users.noreply.github.com> Date: Mon, 17 Jun 2024 19:58:42 +0200 Subject: [PATCH 02/13] Just rename "event.c" to "_event.c". --- buildconfig/Setup.Android.SDL2.in | 2 +- buildconfig/Setup.Emscripten.SDL2.in | 2 +- buildconfig/Setup.SDL2.in | 2 +- src_c/{event.c => _event.c} | 8 ++++---- src_c/display.c | 4 ++-- src_c/include/_pygame.h | 28 +++++++++++++++------------- src_c/meson.build | 6 +++--- src_c/static.c | 6 +++--- src_py/event.py | 1 + src_py/meson.build | 1 + 10 files changed, 32 insertions(+), 28 deletions(-) rename src_c/{event.c => _event.c} (99%) create mode 100644 src_py/event.py diff --git a/buildconfig/Setup.Android.SDL2.in b/buildconfig/Setup.Android.SDL2.in index fc556ad024..5ef285a55e 100644 --- a/buildconfig/Setup.Android.SDL2.in +++ b/buildconfig/Setup.Android.SDL2.in @@ -43,7 +43,7 @@ base src_c/base.c $(SDL) $(DEBUG) color src_c/color.c $(SDL) $(DEBUG) constants src_c/constants.c $(SDL) $(DEBUG) display src_c/display.c $(SDL) $(DEBUG) -event src_c/event.c $(SDL) $(DEBUG) +_event src_c/_event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) diff --git a/buildconfig/Setup.Emscripten.SDL2.in b/buildconfig/Setup.Emscripten.SDL2.in index 23b22f5766..2912b6d3a3 100644 --- a/buildconfig/Setup.Emscripten.SDL2.in +++ b/buildconfig/Setup.Emscripten.SDL2.in @@ -46,7 +46,7 @@ color src_c/void.c controller_old src_c/void.c display src_c/void.c draw src_c/void.c -event src_c/void.c +_event src_c/void.c font src_c/void.c gfxdraw src_c/void.c joystick src_c/void.c diff --git a/buildconfig/Setup.SDL2.in b/buildconfig/Setup.SDL2.in index 2fd66eeea3..e789e029f5 100644 --- a/buildconfig/Setup.SDL2.in +++ b/buildconfig/Setup.SDL2.in @@ -53,7 +53,7 @@ base src_c/base.c $(SDL) $(DEBUG) color src_c/color.c $(SDL) $(DEBUG) constants src_c/constants.c $(SDL) $(DEBUG) display src_c/display.c $(SDL) $(DEBUG) -event src_c/event.c $(SDL) $(DEBUG) +_event src_c/_event.c $(SDL) $(DEBUG) key src_c/key.c $(SDL) $(DEBUG) mouse src_c/mouse.c $(SDL) $(DEBUG) rect src_c/rect.c src_c/pgcompat_rect.c $(SDL) $(DEBUG) diff --git a/src_c/event.c b/src_c/_event.c similarity index 99% rename from src_c/event.c rename to src_c/_event.c index 5a83df7adc..9f199f4c1f 100644 --- a/src_c/event.c +++ b/src_c/_event.c @@ -2240,9 +2240,9 @@ pg_event_custom_type(PyObject *self, PyObject *_null) } static PyMethodDef _event_methods[] = { - {"_internal_mod_init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, + {"init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, "auto initialize for event module"}, - {"_internal_mod_quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, + {"quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, "auto quit for event module"}, {"event_name", event_name, METH_VARARGS, DOC_EVENT_EVENTNAME}, @@ -2273,7 +2273,7 @@ static PyMethodDef _event_methods[] = { {NULL, NULL, 0, NULL}}; -MODINIT_DEFINE(event) +MODINIT_DEFINE(_event) { PyObject *module, *apiobj; static void *c_api[PYGAMEAPI_EVENT_NUMSLOTS]; @@ -2338,7 +2338,7 @@ MODINIT_DEFINE(event) c_api[8] = pgEvent_GetMouseButtonDownInfo; c_api[9] = pgEvent_GetMouseButtonUpInfo; - apiobj = encapsulate_api(c_api, "event"); + apiobj = encapsulate_api(c_api, "_event"); if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { Py_XDECREF(apiobj); Py_DECREF(module); diff --git a/src_c/display.c b/src_c/display.c index ff14e8ad5f..c7d9ab8746 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -184,7 +184,7 @@ pg_display_quit(PyObject *self, PyObject *_null) pg_SetDefaultWindow(NULL); } - pg_mod_autoquit(IMPPREFIX "event"); + pg_mod_autoquit(IMPPREFIX "_event"); pg_mod_autoquit(IMPPREFIX "time"); pg_mod_autoquit(IMPPREFIX "window"); @@ -240,7 +240,7 @@ pg_display_init(PyObject *self, PyObject *_null) if (!pg_mod_autoinit(IMPPREFIX "time")) return NULL; - if (!pg_mod_autoinit(IMPPREFIX "event")) + if (!pg_mod_autoinit(IMPPREFIX "_event")) return NULL; if (!pg_mod_autoinit(IMPPREFIX "window")) return NULL; diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index e1510b7756..77a01981c5 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -381,34 +381,36 @@ typedef struct { typedef struct pgEventObject pgEventObject; #ifndef PYGAMEAPI_EVENT_INTERNAL -#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(event, 0)) +#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_event, 0)) #define pgEvent_Check(x) ((x)->ob_type == &pgEvent_Type) #define pgEvent_New \ - (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(event, 1)) + (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(_event, 1)) #define pg_post_event \ - (*(int (*)(Uint32, PyObject *))PYGAMEAPI_GET_SLOT(event, 2)) + (*(int (*)(Uint32, PyObject *))PYGAMEAPI_GET_SLOT(_event, 2)) #define pg_post_event_dictproxy \ - (*(int (*)(Uint32, pgEventDictProxy *))PYGAMEAPI_GET_SLOT(event, 3)) + (*(int (*)(Uint32, pgEventDictProxy *))PYGAMEAPI_GET_SLOT(_event, 3)) -#define pg_EnableKeyRepeat (*(int (*)(int, int))PYGAMEAPI_GET_SLOT(event, 4)) +#define pg_EnableKeyRepeat (*(int (*)(int, int))PYGAMEAPI_GET_SLOT(_event, 4)) -#define pg_GetKeyRepeat (*(void (*)(int *, int *))PYGAMEAPI_GET_SLOT(event, 5)) +#define pg_GetKeyRepeat \ + (*(void (*)(int *, int *))PYGAMEAPI_GET_SLOT(_event, 5)) -#define pgEvent_GetKeyDownInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 6)) +#define pgEvent_GetKeyDownInfo \ + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 6)) -#define pgEvent_GetKeyUpInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 7)) +#define pgEvent_GetKeyUpInfo (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 7)) #define pgEvent_GetMouseButtonDownInfo \ - (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 8)) + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 8)) #define pgEvent_GetMouseButtonUpInfo \ - (*(char *(*)(void))PYGAMEAPI_GET_SLOT(event, 9)) + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 9)) -#define import_pygame_event() IMPORT_PYGAME_MODULE(event) +#define import_pygame_event() IMPORT_PYGAME_MODULE(_event) #endif /* @@ -529,7 +531,7 @@ PYGAMEAPI_DEFINE_SLOTS(joystick); PYGAMEAPI_DEFINE_SLOTS(display); PYGAMEAPI_DEFINE_SLOTS(surface); PYGAMEAPI_DEFINE_SLOTS(surflock); -PYGAMEAPI_DEFINE_SLOTS(event); +PYGAMEAPI_DEFINE_SLOTS(_event); PYGAMEAPI_DEFINE_SLOTS(rwobject); PYGAMEAPI_DEFINE_SLOTS(pixelarray); PYGAMEAPI_DEFINE_SLOTS(color); @@ -543,7 +545,7 @@ PYGAMEAPI_EXTERN_SLOTS(joystick); PYGAMEAPI_EXTERN_SLOTS(display); PYGAMEAPI_EXTERN_SLOTS(surface); PYGAMEAPI_EXTERN_SLOTS(surflock); -PYGAMEAPI_EXTERN_SLOTS(event); +PYGAMEAPI_EXTERN_SLOTS(_event); PYGAMEAPI_EXTERN_SLOTS(rwobject); PYGAMEAPI_EXTERN_SLOTS(pixelarray); PYGAMEAPI_EXTERN_SLOTS(color); diff --git a/src_c/meson.build b/src_c/meson.build index 8e8287c834..2b8ff2e27d 100644 --- a/src_c/meson.build +++ b/src_c/meson.build @@ -35,9 +35,9 @@ display = py.extension_module( subdir: pg, ) -event = py.extension_module( - 'event', - 'event.c', +_event = py.extension_module( + '_event', + '_event.c', c_args: warnings_error, dependencies: pg_base_deps, install: true, diff --git a/src_c/static.c b/src_c/static.c index c8929de6e7..6d220fc54d 100644 --- a/src_c/static.c +++ b/src_c/static.c @@ -115,7 +115,7 @@ PyInit_mouse(void); PyMODINIT_FUNC PyInit_key(void); PyMODINIT_FUNC -PyInit_event(void); +PyInit__event(void); PyMODINIT_FUNC PyInit_joystick(void); @@ -308,7 +308,7 @@ PyInit_pygame_static() load_submodule("pygame", PyInit_mask(), "mask"); load_submodule("pygame", PyInit_mouse(), "mouse"); - load_submodule("pygame", PyInit_event(), "event"); + load_submodule("pygame", PyInit__event(), "_event"); load_submodule("pygame", PyInit_joystick(), "joystick"); load_submodule("pygame", PyInit_pg_mixer(), "mixer"); @@ -391,7 +391,7 @@ PyInit_pygame_static() #include "joystick.c" -#include "event.c" +#include "_event.c" #include "mouse.c" diff --git a/src_py/event.py b/src_py/event.py new file mode 100644 index 0000000000..e1c5e04fd5 --- /dev/null +++ b/src_py/event.py @@ -0,0 +1 @@ +from pygame._event import * diff --git a/src_py/meson.build b/src_py/meson.build index 561aebaadb..28607b75a3 100644 --- a/src_py/meson.build +++ b/src_py/meson.build @@ -8,6 +8,7 @@ python_sources = files( 'camera.py', 'colordict.py', 'cursors.py', + 'event.py', 'freetype.py', 'ftfont.py', 'locals.py', From 3009fe13690678d3d455ff7070d19275dee4e771 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:50:25 +0200 Subject: [PATCH 03/13] Move custom_type() to python. --- buildconfig/stubs/pygame/_event.pyi | 47 +++++++++++++++++++++++++++++ src_c/_event.c | 26 ++-------------- src_py/event.py | 37 ++++++++++++++++++++++- 3 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 buildconfig/stubs/pygame/_event.pyi diff --git a/buildconfig/stubs/pygame/_event.pyi b/buildconfig/stubs/pygame/_event.pyi new file mode 100644 index 0000000000..dc9a1c852f --- /dev/null +++ b/buildconfig/stubs/pygame/_event.pyi @@ -0,0 +1,47 @@ +from typing import ( + Any, + Dict, + List, + Optional, + Union, + final, +) + +from ._common import Sequence + +@final +class Event: + type: int + dict: Dict[str, Any] + __dict__: Dict[str, Any] + __hash__: None # type: ignore + def __init__( + self, type: int, dict: Dict[str, Any] = ..., **kwargs: Any + ) -> None: ... + def __getattribute__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + def __delattr__(self, name: str) -> None: ... + def __bool__(self) -> bool: ... + +_EventTypes = Union[int, Sequence[int]] + +def pump() -> None: ... +def get( + eventtype: Optional[_EventTypes] = None, + pump: Any = True, + exclude: Optional[_EventTypes] = None, +) -> List[Event]: ... +def poll() -> Event: ... +def wait(timeout: int = 0) -> Event: ... +def peek(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> bool: ... +def clear(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> None: ... +def event_name(type: int, /) -> str: ... +def set_blocked(type: Optional[_EventTypes], /) -> None: ... +def set_allowed(type: Optional[_EventTypes], /) -> None: ... +def get_blocked(type: _EventTypes, /) -> bool: ... +def set_grab(grab: bool, /) -> None: ... +def get_grab() -> bool: ... +def post(event: Event, /) -> bool: ... +def custom_type() -> int: ... + +EventType = Event diff --git a/src_c/_event.c b/src_c/_event.c index 9f199f4c1f..7e977a9930 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -49,11 +49,6 @@ #define PG_GET_LIST_LEN 128 -/* _custom_event stores the next custom user event type that will be - * returned by pygame.event.custom_type() */ -#define _PGE_CUSTOM_EVENT_INIT PGE_USEREVENT + 1 - -static int _custom_event = _PGE_CUSTOM_EVENT_INIT; static int _pg_event_is_init = 0; /* Length of our unicode string in bytes. We need 1 to 3 bytes to store @@ -638,11 +633,6 @@ pgEvent_AutoQuit(PyObject *self, PyObject *_null) _pg_repeat_timer = 0; } PG_UNLOCK_EVFILTER_MUTEX - /* The main reason for _custom_event to be reset here is so we - * can have a unit test that checks if pygame.event.custom_type() - * stops returning new types when they are finished, without that - * test preventing further tests from getting a custom event type.*/ - _custom_event = _PGE_CUSTOM_EVENT_INIT; } _pg_event_is_init = 0; Py_RETURN_NONE; @@ -2229,20 +2219,10 @@ pg_event_get_blocked(PyObject *self, PyObject *obj) return PyBool_FromLong(isblocked); } -static PyObject * -pg_event_custom_type(PyObject *self, PyObject *_null) -{ - if (_custom_event < PG_NUMEVENTS) - return PyLong_FromLong(_custom_event++); - else - return RAISE(pgExc_SDLError, - "pygame.event.custom_type made too many event types."); -} - static PyMethodDef _event_methods[] = { - {"init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, + {"_internal_mod_init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, "auto initialize for event module"}, - {"quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, + {"_internal_mod_quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, "auto quit for event module"}, {"event_name", event_name, METH_VARARGS, DOC_EVENT_EVENTNAME}, @@ -2268,8 +2248,6 @@ static PyMethodDef _event_methods[] = { DOC_EVENT_SETBLOCKED}, {"get_blocked", (PyCFunction)pg_event_get_blocked, METH_O, DOC_EVENT_GETBLOCKED}, - {"custom_type", (PyCFunction)pg_event_custom_type, METH_NOARGS, - DOC_EVENT_CUSTOMTYPE}, {NULL, NULL, 0, NULL}}; diff --git a/src_py/event.py b/src_py/event.py index e1c5e04fd5..f4ecbda2bc 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -1 +1,36 @@ -from pygame._event import * +from pygame._event import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] +from pygame.constants import USEREVENT, NUMEVENTS +from pygame.base import error + + +_is_init = False +_custom_event = USEREVENT + 1 + + +def init(): + global _is_init + + _internal_mod_init() + + _is_init = True + + +def quit(): + global _is_init, _custom_event + + # The main reason for _custom_event to be reset here is so we can have a unit test that checks if pygame.event.custom_type() stops returning new types when they are finished, without that test preventing further tests from getting a custom event type. + _custom_event = USEREVENT + 1 + _internal_mod_quit() + + _is_init = False + + +def custom_type(): + """custom_type() -> int\nmake custom user event type""" + global _custom_event + + if _custom_event < NUMEVENTS: + _custom_event += 1 + return _custom_event - 1 + else: + raise error("pygame.event.custom_type made too many event types.") From 549805e7cb4a17d25af62e85b0777a0373ea4e74 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:05:46 +0200 Subject: [PATCH 04/13] Bugfix --- buildconfig/stubs/pygame/_event.pyi | 1 - src_c/display.c | 4 ++-- src_py/event.py | 5 +++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/buildconfig/stubs/pygame/_event.pyi b/buildconfig/stubs/pygame/_event.pyi index dc9a1c852f..f684f3f61e 100644 --- a/buildconfig/stubs/pygame/_event.pyi +++ b/buildconfig/stubs/pygame/_event.pyi @@ -42,6 +42,5 @@ def get_blocked(type: _EventTypes, /) -> bool: ... def set_grab(grab: bool, /) -> None: ... def get_grab() -> bool: ... def post(event: Event, /) -> bool: ... -def custom_type() -> int: ... EventType = Event diff --git a/src_c/display.c b/src_c/display.c index c7d9ab8746..ff14e8ad5f 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -184,7 +184,7 @@ pg_display_quit(PyObject *self, PyObject *_null) pg_SetDefaultWindow(NULL); } - pg_mod_autoquit(IMPPREFIX "_event"); + pg_mod_autoquit(IMPPREFIX "event"); pg_mod_autoquit(IMPPREFIX "time"); pg_mod_autoquit(IMPPREFIX "window"); @@ -240,7 +240,7 @@ pg_display_init(PyObject *self, PyObject *_null) if (!pg_mod_autoinit(IMPPREFIX "time")) return NULL; - if (!pg_mod_autoinit(IMPPREFIX "_event")) + if (!pg_mod_autoinit(IMPPREFIX "event")) return NULL; if (!pg_mod_autoinit(IMPPREFIX "window")) return NULL; diff --git a/src_py/event.py b/src_py/event.py index f4ecbda2bc..7d18dfeb11 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -1,4 +1,5 @@ from pygame._event import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] +from pygame._event import _internal_mod_init as _init, _internal_mod_quit as _quit from pygame.constants import USEREVENT, NUMEVENTS from pygame.base import error @@ -10,7 +11,7 @@ def init(): global _is_init - _internal_mod_init() + _init() _is_init = True @@ -20,7 +21,7 @@ def quit(): # The main reason for _custom_event to be reset here is so we can have a unit test that checks if pygame.event.custom_type() stops returning new types when they are finished, without that test preventing further tests from getting a custom event type. _custom_event = USEREVENT + 1 - _internal_mod_quit() + _quit() _is_init = False From f333b6ee89424adda7a48afe9c67e5c7403956d8 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:02:43 +0200 Subject: [PATCH 05/13] Move event_name() to python. --- buildconfig/stubs/pygame/_event.pyi | 1 - src_c/_event.c | 12 ---- src_c/base.c | 4 ++ src_py/event.py | 92 ++++++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/buildconfig/stubs/pygame/_event.pyi b/buildconfig/stubs/pygame/_event.pyi index f684f3f61e..9b51f700dd 100644 --- a/buildconfig/stubs/pygame/_event.pyi +++ b/buildconfig/stubs/pygame/_event.pyi @@ -35,7 +35,6 @@ def poll() -> Event: ... def wait(timeout: int = 0) -> Event: ... def peek(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> bool: ... def clear(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> None: ... -def event_name(type: int, /) -> str: ... def set_blocked(type: Optional[_EventTypes], /) -> None: ... def set_allowed(type: Optional[_EventTypes], /) -> None: ... def get_blocked(type: _EventTypes, /) -> bool: ... diff --git a/src_c/_event.c b/src_c/_event.c index 7e977a9930..f1e5d1289e 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -1544,16 +1544,6 @@ pgEvent_New(SDL_Event *event) /* event module functions */ -static PyObject * -event_name(PyObject *self, PyObject *arg) -{ - int type; - if (!PyArg_ParseTuple(arg, "i", &type)) - return NULL; - - return PyUnicode_FromString(_pg_name_from_eventtype(type)); -} - static PyObject * set_grab(PyObject *self, PyObject *arg) { @@ -2225,8 +2215,6 @@ static PyMethodDef _event_methods[] = { {"_internal_mod_quit", (PyCFunction)pgEvent_AutoQuit, METH_NOARGS, "auto quit for event module"}, - {"event_name", event_name, METH_VARARGS, DOC_EVENT_EVENTNAME}, - {"set_grab", set_grab, METH_O, DOC_EVENT_SETGRAB}, {"get_grab", (PyCFunction)get_grab, METH_NOARGS, DOC_EVENT_GETGRAB}, diff --git a/src_c/base.c b/src_c/base.c index 2a609e6601..03f58868e7 100644 --- a/src_c/base.c +++ b/src_c/base.c @@ -296,6 +296,10 @@ pg_mod_autoquit(const char *modname) funcobj = PyObject_GetAttrString(module, "_internal_mod_quit"); + /* Silence errors */ + if (PyErr_Occurred()) + PyErr_Clear(); + /* If we could not load _internal_mod_quit, load quit function */ if (!funcobj) funcobj = PyObject_GetAttrString(module, "quit"); diff --git a/src_py/event.py b/src_py/event.py index 7d18dfeb11..2205c06f14 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -6,6 +6,93 @@ _is_init = False _custom_event = USEREVENT + 1 +_NAMES_MAPPING = { + 32768: "ActiveEvent", + 257: "AppTerminating", + 258: "AppLowMemory", + 259: "AppWillEnterBackground", + 260: "AppDidEnterBackground", + 261: "AppWillEnterForeground", + 262: "AppDidEnterForeground", + 2304: "ClipboardUpdate", + 768: "KeyDown", + 769: "KeyUp", + 772: "KeyMapChanged", + 263: "LocaleChanged", + 1024: "MouseMotion", + 1025: "MouseButtonDown", + 1026: "MouseButtonUp", + 1536: "JoyAxisMotion", + 1537: "JoyBallMotion", + 1538: "JoyHatMotion", + 1540: "JoyButtonUp", + 1539: "JoyButtonDown", + 256: "Quit", + 513: "SysWMEvent", + 32769: "VideoResize", + 32770: "VideoExpose", + 32771: "MidiIn", + 32772: "MidiOut", + 0: "NoEvent", + 1794: "FingerMotion", + 1792: "FingerDown", + 1793: "FingerUp", + 2050: "MultiGesture", + 1027: "MouseWheel", + 771: "TextInput", + 770: "TextEditing", + 4096: "DropFile", + 4097: "DropText", + 4098: "DropBegin", + 4099: "DropComplete", + 1616: "ControllerAxisMotion", + 1617: "ControllerButtonDown", + 1618: "ControllerButtonUp", + 1619: "ControllerDeviceAdded", + 1620: "ControllerDeviceRemoved", + 1621: "ControllerDeviceMapped", + 1541: "JoyDeviceAdded", + 1542: "JoyDeviceRemoved", + 1622: "ControllerTouchpadDown", + 1623: "ControllerTouchpadMotion", + 1624: "ControllerTouchpadUp", + 1625: "ControllerSensorUpdate", + 4352: "AudioDeviceAdded", + 4353: "AudioDeviceRemoved", + 8192: "RenderTargetsReset", + 8193: "RenderDeviceReset", + 32774: "WindowShown", + 32775: "WindowHidden", + 32776: "WindowExposed", + 32777: "WindowMoved", + 32778: "WindowResized", + 32779: "WindowSizeChanged", + 32780: "WindowMinimized", + 32781: "WindowMaximized", + 32782: "WindowRestored", + 32783: "WindowEnter", + 32784: "WindowLeave", + 32785: "WindowFocusGained", + 32786: "WindowFocusLost", + 32787: "WindowClose", + 32788: "WindowTakeFocus", + 32789: "WindowHitTest", + 32790: "WindowICCProfChanged", + 32791: "WindowDisplayChanged", +} + + +def event_name(type: int): + if type in _NAMES_MAPPING: + return _NAMES_MAPPING[type] + elif type >= USEREVENT and type < NUMEVENTS: + return "UserEvent" + return "Unknown" + + +# class Event: +# def __init__(self, type: int): +# self.type = type def init(): @@ -19,7 +106,10 @@ def init(): def quit(): global _is_init, _custom_event - # The main reason for _custom_event to be reset here is so we can have a unit test that checks if pygame.event.custom_type() stops returning new types when they are finished, without that test preventing further tests from getting a custom event type. + # The main reason for _custom_event to be reset here is + # so we can have a unit test that checks if pygame.event.custom_type() stops + # returning new types when they are finished, + # without that test preventing further tests from getting a custom event type. _custom_event = USEREVENT + 1 _quit() From 8485bdd25efb2ecbf6aabd940c46ceceda566ab7 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Wed, 17 Jul 2024 13:31:49 +0200 Subject: [PATCH 06/13] Update _NAMES_MAPPING --- buildconfig/stubs/pygame/event.pyi | 4 +- src_py/event.py | 157 +++++++++++++++-------------- 2 files changed, 82 insertions(+), 79 deletions(-) diff --git a/buildconfig/stubs/pygame/event.pyi b/buildconfig/stubs/pygame/event.pyi index dc9a1c852f..9f4bd597ac 100644 --- a/buildconfig/stubs/pygame/event.pyi +++ b/buildconfig/stubs/pygame/event.pyi @@ -35,7 +35,7 @@ def poll() -> Event: ... def wait(timeout: int = 0) -> Event: ... def peek(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> bool: ... def clear(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> None: ... -def event_name(type: int, /) -> str: ... +def event_name(type: int) -> str: ... def set_blocked(type: Optional[_EventTypes], /) -> None: ... def set_allowed(type: Optional[_EventTypes], /) -> None: ... def get_blocked(type: _EventTypes, /) -> bool: ... @@ -43,5 +43,7 @@ def set_grab(grab: bool, /) -> None: ... def get_grab() -> bool: ... def post(event: Event, /) -> bool: ... def custom_type() -> int: ... +def init(): ... +def quit(): ... EventType = Event diff --git a/src_py/event.py b/src_py/event.py index 2205c06f14..36f6b9522f 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -2,90 +2,91 @@ from pygame._event import _internal_mod_init as _init, _internal_mod_quit as _quit from pygame.constants import USEREVENT, NUMEVENTS from pygame.base import error +import pygame as pg _is_init = False _custom_event = USEREVENT + 1 _NAMES_MAPPING = { - 32768: "ActiveEvent", - 257: "AppTerminating", - 258: "AppLowMemory", - 259: "AppWillEnterBackground", - 260: "AppDidEnterBackground", - 261: "AppWillEnterForeground", - 262: "AppDidEnterForeground", - 2304: "ClipboardUpdate", - 768: "KeyDown", - 769: "KeyUp", - 772: "KeyMapChanged", - 263: "LocaleChanged", - 1024: "MouseMotion", - 1025: "MouseButtonDown", - 1026: "MouseButtonUp", - 1536: "JoyAxisMotion", - 1537: "JoyBallMotion", - 1538: "JoyHatMotion", - 1540: "JoyButtonUp", - 1539: "JoyButtonDown", - 256: "Quit", - 513: "SysWMEvent", - 32769: "VideoResize", - 32770: "VideoExpose", - 32771: "MidiIn", - 32772: "MidiOut", - 0: "NoEvent", - 1794: "FingerMotion", - 1792: "FingerDown", - 1793: "FingerUp", - 2050: "MultiGesture", - 1027: "MouseWheel", - 771: "TextInput", - 770: "TextEditing", - 4096: "DropFile", - 4097: "DropText", - 4098: "DropBegin", - 4099: "DropComplete", - 1616: "ControllerAxisMotion", - 1617: "ControllerButtonDown", - 1618: "ControllerButtonUp", - 1619: "ControllerDeviceAdded", - 1620: "ControllerDeviceRemoved", - 1621: "ControllerDeviceMapped", - 1541: "JoyDeviceAdded", - 1542: "JoyDeviceRemoved", - 1622: "ControllerTouchpadDown", - 1623: "ControllerTouchpadMotion", - 1624: "ControllerTouchpadUp", - 1625: "ControllerSensorUpdate", - 4352: "AudioDeviceAdded", - 4353: "AudioDeviceRemoved", - 8192: "RenderTargetsReset", - 8193: "RenderDeviceReset", - 32774: "WindowShown", - 32775: "WindowHidden", - 32776: "WindowExposed", - 32777: "WindowMoved", - 32778: "WindowResized", - 32779: "WindowSizeChanged", - 32780: "WindowMinimized", - 32781: "WindowMaximized", - 32782: "WindowRestored", - 32783: "WindowEnter", - 32784: "WindowLeave", - 32785: "WindowFocusGained", - 32786: "WindowFocusLost", - 32787: "WindowClose", - 32788: "WindowTakeFocus", - 32789: "WindowHitTest", - 32790: "WindowICCProfChanged", - 32791: "WindowDisplayChanged", + pg.ACTIVEEVENT: "ActiveEvent", + pg.APP_TERMINATING: "AppTerminating", + pg.APP_LOWMEMORY: "AppLowMemory", + pg.APP_WILLENTERBACKGROUND: "AppWillEnterBackground", + pg.APP_DIDENTERBACKGROUND: "AppDidEnterBackground", + pg.APP_WILLENTERFOREGROUND: "AppWillEnterForeground", + pg.APP_DIDENTERFOREGROUND: "AppDidEnterForeground", + pg.CLIPBOARDUPDATE: "ClipboardUpdate", + pg.KEYDOWN: "KeyDown", + pg.KEYUP: "KeyUp", + pg.KEYMAPCHANGED: "KeyMapChanged", + pg.LOCALECHANGED: "LocaleChanged", + pg.MOUSEMOTION: "MouseMotion", + pg.MOUSEBUTTONDOWN: "MouseButtonDown", + pg.MOUSEBUTTONUP: "MouseButtonUp", + pg.JOYAXISMOTION: "JoyAxisMotion", + pg.JOYBALLMOTION: "JoyBallMotion", + pg.JOYHATMOTION: "JoyHatMotion", + pg.JOYBUTTONUP: "JoyButtonUp", + pg.JOYBUTTONDOWN: "JoyButtonDown", + pg.QUIT: "Quit", + pg.SYSWMEVENT: "SysWMEvent", + pg.VIDEORESIZE: "VideoResize", + pg.VIDEOEXPOSE: "VideoExpose", + pg.MIDIIN: "MidiIn", + pg.MIDIOUT: "MidiOut", + pg.NOEVENT: "NoEvent", + pg.FINGERMOTION: "FingerMotion", + pg.FINGERDOWN: "FingerDown", + pg.FINGERUP: "FingerUp", + pg.MULTIGESTURE: "MultiGesture", + pg.MOUSEWHEEL: "MouseWheel", + pg.TEXTINPUT: "TextInput", + pg.TEXTEDITING: "TextEditing", + pg.DROPFILE: "DropFile", + pg.DROPTEXT: "DropText", + pg.DROPBEGIN: "DropBegin", + pg.DROPCOMPLETE: "DropComplete", + pg.CONTROLLERAXISMOTION: "ControllerAxisMotion", + pg.CONTROLLERBUTTONDOWN: "ControllerButtonDown", + pg.CONTROLLERBUTTONUP: "ControllerButtonUp", + pg.CONTROLLERDEVICEADDED: "ControllerDeviceAdded", + pg.CONTROLLERDEVICEREMOVED: "ControllerDeviceRemoved", + pg.CONTROLLERDEVICEREMAPPED: "ControllerDeviceMapped", + pg.JOYDEVICEADDED: "JoyDeviceAdded", + pg.JOYDEVICEREMOVED: "JoyDeviceRemoved", + pg.CONTROLLERTOUCHPADDOWN: "ControllerTouchpadDown", + pg.CONTROLLERTOUCHPADMOTION: "ControllerTouchpadMotion", + pg.CONTROLLERTOUCHPADUP: "ControllerTouchpadUp", + pg.CONTROLLERSENSORUPDATE: "ControllerSensorUpdate", + pg.AUDIODEVICEADDED: "AudioDeviceAdded", + pg.AUDIODEVICEREMOVED: "AudioDeviceRemoved", + pg.RENDER_TARGETS_RESET: "RenderTargetsReset", + pg.RENDER_DEVICE_RESET: "RenderDeviceReset", + pg.WINDOWSHOWN: "WindowShown", + pg.WINDOWHIDDEN: "WindowHidden", + pg.WINDOWEXPOSED: "WindowExposed", + pg.WINDOWMOVED: "WindowMoved", + pg.WINDOWRESIZED: "WindowResized", + pg.WINDOWSIZECHANGED: "WindowSizeChanged", + pg.WINDOWMINIMIZED: "WindowMinimized", + pg.WINDOWMAXIMIZED: "WindowMaximized", + pg.WINDOWRESTORED: "WindowRestored", + pg.WINDOWENTER: "WindowEnter", + pg.WINDOWLEAVE: "WindowLeave", + pg.WINDOWFOCUSGAINED: "WindowFocusGained", + pg.WINDOWFOCUSLOST: "WindowFocusLost", + pg.WINDOWCLOSE: "WindowClose", + pg.WINDOWTAKEFOCUS: "WindowTakeFocus", + pg.WINDOWHITTEST: "WindowHitTest", + pg.WINDOWICCPROFCHANGED: "WindowICCProfChanged", + pg.WINDOWDISPLAYCHANGED: "WindowDisplayChanged", } -def event_name(type: int): +def event_name(type: int) -> str: if type in _NAMES_MAPPING: return _NAMES_MAPPING[type] - elif type >= USEREVENT and type < NUMEVENTS: + elif USEREVENT <= type < NUMEVENTS: return "UserEvent" return "Unknown" @@ -120,8 +121,8 @@ def custom_type(): """custom_type() -> int\nmake custom user event type""" global _custom_event - if _custom_event < NUMEVENTS: - _custom_event += 1 - return _custom_event - 1 - else: + if _custom_event >= NUMEVENTS: raise error("pygame.event.custom_type made too many event types.") + + _custom_event += 1 + return _custom_event - 1 From 1b10fd9207d9f3a3432a41f7bd6794bb6fe8ce15 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Thu, 18 Jul 2024 21:06:42 +0200 Subject: [PATCH 07/13] Moving Event() to python, likely not working yet. --- buildconfig/stubs/pygame/_event.pyi | 19 +- src_c/_event.c | 325 ++++++++++------------------ src_c/_pygame.h | 6 +- src_c/include/_pygame.h | 17 +- src_c/time.c | 26 ++- src_py/event.py | 44 +++- 6 files changed, 185 insertions(+), 252 deletions(-) diff --git a/buildconfig/stubs/pygame/_event.pyi b/buildconfig/stubs/pygame/_event.pyi index 9b51f700dd..237557f21a 100644 --- a/buildconfig/stubs/pygame/_event.pyi +++ b/buildconfig/stubs/pygame/_event.pyi @@ -1,28 +1,12 @@ from typing import ( Any, - Dict, List, Optional, Union, - final, ) from ._common import Sequence -@final -class Event: - type: int - dict: Dict[str, Any] - __dict__: Dict[str, Any] - __hash__: None # type: ignore - def __init__( - self, type: int, dict: Dict[str, Any] = ..., **kwargs: Any - ) -> None: ... - def __getattribute__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __delattr__(self, name: str) -> None: ... - def __bool__(self) -> bool: ... - _EventTypes = Union[int, Sequence[int]] def pump() -> None: ... @@ -41,5 +25,4 @@ def get_blocked(type: _EventTypes, /) -> bool: ... def set_grab(grab: bool, /) -> None: ... def get_grab() -> bool: ... def post(event: Event, /) -> bool: ... - -EventType = Event +def register_event_class(cls: type): ... diff --git a/src_c/_event.c b/src_c/_event.c index f1e5d1289e..b14262e405 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -93,6 +93,8 @@ static char released_keys[SDL_NUM_SCANCODES] = {0}; static char pressed_mouse_buttons[5] = {0}; static char released_mouse_buttons[5] = {0}; +static PyObject *_event_class = NULL; + #ifdef __EMSCRIPTEN__ /* these macros are no-op here */ #define PG_LOCK_EVFILTER_MUTEX @@ -1328,218 +1330,101 @@ dict_from_event(SDL_Event *event) return dict; } -/* event object internals */ - -static void -pg_event_dealloc(PyObject *self) +static PyObject * +pgEvent_GetType(void) { - pgEventObject *e = (pgEventObject *)self; - Py_XDECREF(e->dict); - Py_TYPE(self)->tp_free(self); -} + if (!_event_class) + return RAISE(PyExc_RuntimeError, "event type is currently unknown"); -#ifdef PYPY_VERSION -/* Because pypy does not work with the __dict__ tp_dictoffset. */ -PyObject * -pg_EventGetAttr(PyObject *o, PyObject *attr_name) -{ - /* Try e->dict first, if not try the generic attribute. */ - PyObject *result = PyDict_GetItem(((pgEventObject *)o)->dict, attr_name); - if (!result) { - return PyObject_GenericGetAttr(o, attr_name); - } - return result; + Py_INCREF(_event_class); + return _event_class; } -int -pg_EventSetAttr(PyObject *o, PyObject *name, PyObject *value) +static PyObject * +pgEvent_FromEventData(pgEventData e_data) { - /* if the variable is in the dict, deal with it there. - else if it's a normal attribute set it there. - else if it's not an attribute, or in the dict, set it in the dict. - */ - int dictResult; - int setInDict = 0; - PyObject *result = PyDict_GetItem(((pgEventObject *)o)->dict, name); + PyObject *ret = NULL; + PyObject *args = NULL; - if (result) { - setInDict = 1; - } - else { - result = PyObject_GenericGetAttr(o, name); - if (!result) { - PyErr_Clear(); - setInDict = 1; - } - } + PyObject *e_type = pgEvent_GetType(); + if (!e_type) + return NULL; - if (setInDict) { - dictResult = PyDict_SetItem(((pgEventObject *)o)->dict, name, value); - if (dictResult) { - return -1; - } - return 0; - } - else { - return PyObject_GenericSetAttr(o, name, value); + PyObject *num = PyLong_FromLong(e_data.type); + if (!num) + goto finalize; + + args = PyTuple_New(1); + if (!args) { + Py_DECREF(num); + goto finalize; } -} -#endif -PyObject * -pg_event_str(PyObject *self) -{ - pgEventObject *e = (pgEventObject *)self; - return PyUnicode_FromFormat("", e->type, - _pg_name_from_eventtype(e->type), e->dict); -} + PyTuple_SetItem(args, 0, num); + ret = PyObject_Call(e_type, args, e_data.dict); -static int -_pg_event_nonzero(pgEventObject *self) -{ - return self->type != SDL_NOEVENT; +finalize: + Py_DECREF(e_type); + Py_XDECREF(args); + return ret; } -static PyNumberMethods pg_event_as_number = { - .nb_bool = (inquiry)_pg_event_nonzero, -}; - -static PyTypeObject pgEvent_Type; -#define pgEvent_Check(x) ((x)->ob_type == &pgEvent_Type) -#define OFF(x) offsetof(pgEventObject, x) - -static PyMemberDef pg_event_members[] = { - {"__dict__", T_OBJECT, OFF(dict), READONLY}, - {"type", T_INT, OFF(type), READONLY}, - {"dict", T_OBJECT, OFF(dict), READONLY}, - {NULL} /* Sentinel */ -}; - -/* - * eventA == eventB - * eventA != eventB - */ -static PyObject * -pg_event_richcompare(PyObject *o1, PyObject *o2, int opid) +static pgEventData +pgEvent_GetEventData(PyObject *event) { - pgEventObject *e1, *e2; - - if (!pgEvent_Check(o1) || !pgEvent_Check(o2)) { - goto Unimplemented; - } - - e1 = (pgEventObject *)o1; - e2 = (pgEventObject *)o2; - switch (opid) { - case Py_EQ: - return PyBool_FromLong( - e1->type == e2->type && - PyObject_RichCompareBool(e1->dict, e2->dict, Py_EQ) == 1); - case Py_NE: - return PyBool_FromLong( - e1->type != e2->type || - PyObject_RichCompareBool(e1->dict, e2->dict, Py_NE) == 1); - default: - break; - } + pgEventData data = {0}; + data.dict = PyObject_GetAttrString(event, "dict"); -Unimplemented: - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; -} + if (PyErr_Occurred()) + PyErr_Clear(); -static int -pg_event_init(pgEventObject *self, PyObject *args, PyObject *kwargs) -{ - int type; - PyObject *dict = NULL; - - if (!PyArg_ParseTuple(args, "i|O!", &type, &PyDict_Type, &dict)) { - return -1; + PyObject *e_typeo = PyObject_GetAttrString(event, "type"); + if (!e_typeo) { + Py_XDECREF(data.dict); + data.dict = NULL; + goto finalize; } - if (type < 0 || type >= PG_NUMEVENTS) { - PyErr_SetString(PyExc_ValueError, "event type out of range"); - return -1; - } + data.type = PyLong_AsLong(e_typeo); - if (!dict) { - if (kwargs) { - dict = kwargs; - Py_INCREF(dict); - } - else { - dict = PyDict_New(); - if (!dict) { - PyErr_NoMemory(); - return -1; - } - } - } - else { - if (kwargs) { - if (PyDict_Update(dict, kwargs) == -1) { - return -1; - } - } - /* So that dict is a new reference */ - Py_INCREF(dict); - } - - if (PyDict_GetItemString(dict, "type")) { - PyErr_SetString(PyExc_ValueError, - "redundant type field in event dict"); - Py_DECREF(dict); - return -1; - } - - self->type = _pg_pgevent_deproxify(type); - self->dict = dict; - return 0; +finalize: + return data; } -static PyTypeObject pgEvent_Type = { - PyVarObject_HEAD_INIT(NULL, 0).tp_name = "pygame.event.Event", - .tp_basicsize = sizeof(pgEventObject), - .tp_dealloc = pg_event_dealloc, - .tp_repr = pg_event_str, - .tp_as_number = &pg_event_as_number, -#ifdef PYPY_VERSION - .tp_getattro = pg_EventGetAttr, - .tp_setattro = pg_EventSetAttr, -#else - .tp_getattro = PyObject_GenericGetAttr, - .tp_setattro = PyObject_GenericSetAttr, -#endif - .tp_doc = DOC_EVENT_EVENT, - .tp_richcompare = pg_event_richcompare, - .tp_members = pg_event_members, - .tp_dictoffset = offsetof(pgEventObject, dict), - .tp_init = (initproc)pg_event_init, - .tp_new = PyType_GenericNew, -}; +static void +pgEvent_FreeEventData(pgEventData e_data) +{ + Py_XDECREF(e_data.dict); + e_data.dict = NULL; +} static PyObject * pgEvent_New(SDL_Event *event) { - pgEventObject *e; - e = PyObject_New(pgEventObject, &pgEvent_Type); - if (!e) - return PyErr_NoMemory(); + pgEventData e = {0}; if (event) { - e->type = _pg_pgevent_deproxify(event->type); - e->dict = dict_from_event(event); + e.type = _pg_pgevent_deproxify(event->type); + e.dict = dict_from_event(event); } else { - e->type = SDL_NOEVENT; - e->dict = PyDict_New(); - } - if (!e->dict) { - Py_TYPE(e)->tp_free(e); - return PyErr_NoMemory(); + e.type = SDL_NOEVENT; } - return (PyObject *)e; + + PyObject *ret = pgEvent_FromEventData(e); + pgEvent_FreeEventData(e); + return ret; +} + +static int +pgEvent_Check(PyObject *obj) +{ + PyObject *e_type = pgEvent_GetType(); + if (!e_type) + return -1; + int res = PyObject_IsInstance(obj, e_type); + Py_DECREF(e_type); + return res; } /* event module functions */ @@ -2097,11 +1982,19 @@ static PyObject * pg_event_post(PyObject *self, PyObject *obj) { VIDEO_INIT_CHECK(); - if (!pgEvent_Check(obj)) + int is_event = pgEvent_Check(obj); + if (is_event < 0) + return NULL; + else if (!is_event) return RAISE(PyExc_TypeError, "argument must be an Event object"); - pgEventObject *e = (pgEventObject *)obj; - switch (pg_post_event(e->type, e->dict)) { + pgEventData e = pgEvent_GetEventData(obj); + + if (PyErr_Occurred()) + return NULL; + + switch (pg_post_event(e.type, e.dict)) { + pgEvent_FreeEventData(e); case 0: Py_RETURN_FALSE; case 1: @@ -2209,6 +2102,25 @@ pg_event_get_blocked(PyObject *self, PyObject *obj) return PyBool_FromLong(isblocked); } +static PyObject * +pg_event_register_event_class(PyObject *self, PyObject *obj) +{ + if (!(PyType_Check(obj) && PyCallable_Check(obj))) + return RAISE(PyExc_ValueError, "expected a type"); + + Py_INCREF(obj); + Py_XDECREF(_event_class); + _event_class = obj; + Py_RETURN_NONE; +} + +void +pg_event_free(PyObject *self) +{ + Py_XDECREF(_event_class); + _event_class = NULL; +} + static PyMethodDef _event_methods[] = { {"_internal_mod_init", (PyCFunction)pgEvent_AutoInit, METH_NOARGS, "auto initialize for event module"}, @@ -2236,6 +2148,8 @@ static PyMethodDef _event_methods[] = { DOC_EVENT_SETBLOCKED}, {"get_blocked", (PyCFunction)pg_event_get_blocked, METH_O, DOC_EVENT_GETBLOCKED}, + {"register_event_class", (PyCFunction)pg_event_register_event_class, + METH_O}, {NULL, NULL, 0, NULL}}; @@ -2244,15 +2158,10 @@ MODINIT_DEFINE(_event) PyObject *module, *apiobj; static void *c_api[PYGAMEAPI_EVENT_NUMSLOTS]; - static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT, - "event", - DOC_EVENT, - -1, - _event_methods, - NULL, - NULL, - NULL, - NULL}; + static struct PyModuleDef _module = { + PyModuleDef_HEAD_INIT, "event", DOC_EVENT, -1, + _event_methods, NULL, NULL, NULL, + (freefunc)pg_event_free}; /* imported needed apis; Do this first so if there is an error the module is not loaded. @@ -2267,33 +2176,15 @@ MODINIT_DEFINE(_event) return NULL; } - /* type preparation */ - if (PyType_Ready(&pgEvent_Type) < 0) { - return NULL; - } - /* create the module */ module = PyModule_Create(&_module); if (!module) { return NULL; } - Py_INCREF(&pgEvent_Type); - if (PyModule_AddObject(module, "EventType", (PyObject *)&pgEvent_Type)) { - Py_DECREF(&pgEvent_Type); - Py_DECREF(module); - return NULL; - } - Py_INCREF(&pgEvent_Type); - if (PyModule_AddObject(module, "Event", (PyObject *)&pgEvent_Type)) { - Py_DECREF(&pgEvent_Type); - Py_DECREF(module); - return NULL; - } - /* export the c api */ - assert(PYGAMEAPI_EVENT_NUMSLOTS == 10); - c_api[0] = &pgEvent_Type; + assert(PYGAMEAPI_EVENT_NUMSLOTS == 14); + c_api[0] = pgEvent_GetType; c_api[1] = pgEvent_New; c_api[2] = pg_post_event; c_api[3] = pg_post_event_dictproxy; @@ -2303,6 +2194,10 @@ MODINIT_DEFINE(_event) c_api[7] = pgEvent_GetKeyUpInfo; c_api[8] = pgEvent_GetMouseButtonDownInfo; c_api[9] = pgEvent_GetMouseButtonUpInfo; + c_api[10] = pgEvent_Check; + c_api[11] = pgEvent_FromEventData; + c_api[12] = pgEvent_GetEventData; + c_api[13] = pgEvent_FreeEventData; apiobj = encapsulate_api(c_api, "_event"); if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj)) { diff --git a/src_c/_pygame.h b/src_c/_pygame.h index f16cbbf5af..6a07592539 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -480,8 +480,8 @@ typedef enum { /* * event module internals */ -struct pgEventObject { - PyObject_HEAD int type; +struct pgEventData { + int type; PyObject *dict; }; @@ -539,7 +539,7 @@ typedef enum { #define PYGAMEAPI_COLOR_NUMSLOTS 5 #define PYGAMEAPI_MATH_NUMSLOTS 2 #define PYGAMEAPI_BASE_NUMSLOTS 29 -#define PYGAMEAPI_EVENT_NUMSLOTS 10 +#define PYGAMEAPI_EVENT_NUMSLOTS 14 #define PYGAMEAPI_WINDOW_NUMSLOTS 1 #define PYGAMEAPI_GEOMETRY_NUMSLOTS 1 diff --git a/src_c/include/_pygame.h b/src_c/include/_pygame.h index 77a01981c5..7e74e0e827 100644 --- a/src_c/include/_pygame.h +++ b/src_c/include/_pygame.h @@ -378,12 +378,10 @@ typedef struct { /* * EVENT module */ -typedef struct pgEventObject pgEventObject; +typedef struct pgEventData pgEventData; #ifndef PYGAMEAPI_EVENT_INTERNAL -#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_event, 0)) - -#define pgEvent_Check(x) ((x)->ob_type == &pgEvent_Type) +#define pgEvent_GetType (*(PyObject * (*)(void)) PYGAMEAPI_GET_SLOT(_event, 0)) #define pgEvent_New \ (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(_event, 1)) @@ -410,6 +408,17 @@ typedef struct pgEventObject pgEventObject; #define pgEvent_GetMouseButtonUpInfo \ (*(char *(*)(void))PYGAMEAPI_GET_SLOT(_event, 9)) +#define pgEvent_Check (*(int (*)(PyObject *))PYGAMEAPI_GET_SLOT(_event, 10)) + +#define pgEvent_FromEventData \ + (*(PyObject * (*)(pgEventData)) PYGAMEAPI_GET_SLOT(_event, 11)) + +#define pgEvent_GetEventData \ + (*(pgEventData(*)(PyObject *))PYGAMEAPI_GET_SLOT(_event, 12)) + +#define pgEvent_FreeEventData \ + (*(void (*)(pgEventData))PYGAMEAPI_GET_SLOT(_event, 13)) + #define import_pygame_event() IMPORT_PYGAME_MODULE(_event) #endif diff --git a/src_c/time.c b/src_c/time.c index 383782d9b3..5abf959c4a 100644 --- a/src_c/time.c +++ b/src_c/time.c @@ -395,7 +395,7 @@ time_set_timer(PyObject *self, PyObject *args, PyObject *kwargs) int ticks, loops = 0; PyObject *obj, *ev_dict = NULL; int ev_type; - pgEventObject *e; + pgEventData e; pgSetTimerErr ecode = PG_TIMER_NO_ERROR; static char *kwids[] = {"event", "millis", "loops", NULL}; @@ -421,14 +421,24 @@ time_set_timer(PyObject *self, PyObject *args, PyObject *kwargs) return RAISE(PyExc_ValueError, "event type out of range"); } } - else if (pgEvent_Check(obj)) { - e = (pgEventObject *)obj; - ev_type = e->type; - ev_dict = e->dict; - } else { - return RAISE(PyExc_TypeError, - "first argument must be an event type or event object"); + int is_event = pgEvent_Check(obj); + if (is_event) { + e = pgEvent_GetEventData(obj); + + if (PyErr_Occurred()) + return NULL; + + ev_type = e.type; + ev_dict = e.dict; + + pgEvent_FreeEventData(e); + } + else { + return RAISE( + PyExc_TypeError, + "first argument must be an event type or event object"); + } } #ifndef __EMSCRIPTEN__ diff --git a/src_py/event.py b/src_py/event.py index 36f6b9522f..8490e9578a 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from pygame._event import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] from pygame._event import _internal_mod_init as _init, _internal_mod_quit as _quit from pygame.constants import USEREVENT, NUMEVENTS @@ -86,14 +88,48 @@ def event_name(type: int) -> str: if type in _NAMES_MAPPING: return _NAMES_MAPPING[type] - elif USEREVENT <= type < NUMEVENTS: + if USEREVENT <= type < NUMEVENTS: return "UserEvent" return "Unknown" -# class Event: -# def __init__(self, type: int): -# self.type = type +class Event: + """ + Event(type, dict) -> Event + Event(type, **attributes) -> Event + pygame object for representing events + """ + + type: int + dict: dict[str, ...] + + def __init__(self, type: int, dict_: dict[str, ...] | None = None, **kwargs): + if not 0 <= type < NUMEVENTS: + raise error("event type out of range") + dict_ = dict_ if dict_ is not None else {} + dict_.update(kwargs) + + if "type" in dict_: + raise error("redundant type field in event dict") + + dict_["type"] = type + + self.__dict__ = dict_ + + def __int__(self): + return self.type + + def __bool__(self): + return self.type != pg.NOEVENT + + def __eq__(self, other: Event): + return self.type == other.type and self.dict == other.dict + + def __repr__(self): + return f" Date: Thu, 18 Jul 2024 21:16:15 +0200 Subject: [PATCH 08/13] Moving Event() to python - bugfix. --- src_c/_event.c | 158 ------------------------------------------------ src_py/event.py | 8 +++ 2 files changed, 8 insertions(+), 158 deletions(-) diff --git a/src_c/_event.c b/src_c/_event.c index b14262e405..6a28f1e6e8 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -722,164 +722,6 @@ pg_post_event(Uint32 type, PyObject *dict) return ret; } -static char * -_pg_name_from_eventtype(int type) -{ - switch (type) { - case SDL_ACTIVEEVENT: - return "ActiveEvent"; - case SDL_APP_TERMINATING: - return "AppTerminating"; - case SDL_APP_LOWMEMORY: - return "AppLowMemory"; - case SDL_APP_WILLENTERBACKGROUND: - return "AppWillEnterBackground"; - case SDL_APP_DIDENTERBACKGROUND: - return "AppDidEnterBackground"; - case SDL_APP_WILLENTERFOREGROUND: - return "AppWillEnterForeground"; - case SDL_APP_DIDENTERFOREGROUND: - return "AppDidEnterForeground"; - case SDL_CLIPBOARDUPDATE: - return "ClipboardUpdate"; - case SDL_KEYDOWN: - return "KeyDown"; - case SDL_KEYUP: - return "KeyUp"; - case SDL_KEYMAPCHANGED: - return "KeyMapChanged"; -#if SDL_VERSION_ATLEAST(2, 0, 14) - case SDL_LOCALECHANGED: - return "LocaleChanged"; -#endif - case SDL_MOUSEMOTION: - return "MouseMotion"; - case SDL_MOUSEBUTTONDOWN: - return "MouseButtonDown"; - case SDL_MOUSEBUTTONUP: - return "MouseButtonUp"; - case SDL_JOYAXISMOTION: - return "JoyAxisMotion"; - case SDL_JOYBALLMOTION: - return "JoyBallMotion"; - case SDL_JOYHATMOTION: - return "JoyHatMotion"; - case SDL_JOYBUTTONUP: - return "JoyButtonUp"; - case SDL_JOYBUTTONDOWN: - return "JoyButtonDown"; - case SDL_QUIT: - return "Quit"; - case SDL_SYSWMEVENT: - return "SysWMEvent"; - case SDL_VIDEORESIZE: - return "VideoResize"; - case SDL_VIDEOEXPOSE: - return "VideoExpose"; - case PGE_MIDIIN: - return "MidiIn"; - case PGE_MIDIOUT: - return "MidiOut"; - case SDL_NOEVENT: - return "NoEvent"; - case SDL_FINGERMOTION: - return "FingerMotion"; - case SDL_FINGERDOWN: - return "FingerDown"; - case SDL_FINGERUP: - return "FingerUp"; - case SDL_MULTIGESTURE: - return "MultiGesture"; - case SDL_MOUSEWHEEL: - return "MouseWheel"; - case SDL_TEXTINPUT: - return "TextInput"; - case SDL_TEXTEDITING: - return "TextEditing"; - case SDL_DROPFILE: - return "DropFile"; - case SDL_DROPTEXT: - return "DropText"; - case SDL_DROPBEGIN: - return "DropBegin"; - case SDL_DROPCOMPLETE: - return "DropComplete"; - case SDL_CONTROLLERAXISMOTION: - return "ControllerAxisMotion"; - case SDL_CONTROLLERBUTTONDOWN: - return "ControllerButtonDown"; - case SDL_CONTROLLERBUTTONUP: - return "ControllerButtonUp"; - case SDL_CONTROLLERDEVICEADDED: - return "ControllerDeviceAdded"; - case SDL_CONTROLLERDEVICEREMOVED: - return "ControllerDeviceRemoved"; - case SDL_CONTROLLERDEVICEREMAPPED: - return "ControllerDeviceMapped"; - case SDL_JOYDEVICEADDED: - return "JoyDeviceAdded"; - case SDL_JOYDEVICEREMOVED: - return "JoyDeviceRemoved"; -#if SDL_VERSION_ATLEAST(2, 0, 14) - case SDL_CONTROLLERTOUCHPADDOWN: - return "ControllerTouchpadDown"; - case SDL_CONTROLLERTOUCHPADMOTION: - return "ControllerTouchpadMotion"; - case SDL_CONTROLLERTOUCHPADUP: - return "ControllerTouchpadUp"; - case SDL_CONTROLLERSENSORUPDATE: - return "ControllerSensorUpdate"; -#endif /*SDL_VERSION_ATLEAST(2, 0, 14)*/ - case SDL_AUDIODEVICEADDED: - return "AudioDeviceAdded"; - case SDL_AUDIODEVICEREMOVED: - return "AudioDeviceRemoved"; - case SDL_RENDER_TARGETS_RESET: - return "RenderTargetsReset"; - case SDL_RENDER_DEVICE_RESET: - return "RenderDeviceReset"; - case PGE_WINDOWSHOWN: - return "WindowShown"; - case PGE_WINDOWHIDDEN: - return "WindowHidden"; - case PGE_WINDOWEXPOSED: - return "WindowExposed"; - case PGE_WINDOWMOVED: - return "WindowMoved"; - case PGE_WINDOWRESIZED: - return "WindowResized"; - case PGE_WINDOWSIZECHANGED: - return "WindowSizeChanged"; - case PGE_WINDOWMINIMIZED: - return "WindowMinimized"; - case PGE_WINDOWMAXIMIZED: - return "WindowMaximized"; - case PGE_WINDOWRESTORED: - return "WindowRestored"; - case PGE_WINDOWENTER: - return "WindowEnter"; - case PGE_WINDOWLEAVE: - return "WindowLeave"; - case PGE_WINDOWFOCUSGAINED: - return "WindowFocusGained"; - case PGE_WINDOWFOCUSLOST: - return "WindowFocusLost"; - case PGE_WINDOWCLOSE: - return "WindowClose"; - case PGE_WINDOWTAKEFOCUS: - return "WindowTakeFocus"; - case PGE_WINDOWHITTEST: - return "WindowHitTest"; - case PGE_WINDOWICCPROFCHANGED: - return "WindowICCProfChanged"; - case PGE_WINDOWDISPLAYCHANGED: - return "WindowDisplayChanged"; - } - if (type >= PGE_USEREVENT && type < PG_NUMEVENTS) - return "UserEvent"; - return "Unknown"; -} - /* Helper for adding objects to dictionaries. Check for errors with PyErr_Occurred() */ static void diff --git a/src_py/event.py b/src_py/event.py index 8490e9578a..bda5e11a68 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -128,6 +128,14 @@ def __eq__(self, other: Event): def __repr__(self): return f" Date: Fri, 19 Jul 2024 15:15:29 +0200 Subject: [PATCH 09/13] Moving Event() to python - bugfix 2. --- src_c/_event.c | 13 +++++++++++-- src_py/event.py | 46 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src_c/_event.c b/src_c/_event.c index 6a28f1e6e8..98616125df 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -1196,14 +1196,23 @@ pgEvent_FromEventData(pgEventData e_data) if (!num) goto finalize; - args = PyTuple_New(1); + if (e_data.dict) + args = PyTuple_New(2); + else + args = PyTuple_New(1); + if (!args) { Py_DECREF(num); goto finalize; } PyTuple_SetItem(args, 0, num); - ret = PyObject_Call(e_type, args, e_data.dict); + if (e_data.dict) { + Py_INCREF(e_data.dict); + PyTuple_SetItem(args, 1, e_data.dict); + } + + ret = PyObject_Call(e_type, args, NULL); finalize: Py_DECREF(e_type); diff --git a/src_py/event.py b/src_py/event.py index bda5e11a68..b04b3ec61a 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -103,18 +103,26 @@ class Event: type: int dict: dict[str, ...] - def __init__(self, type: int, dict_: dict[str, ...] | None = None, **kwargs): + def __init__(self, type: int, dict: dict[str, ...] | None = None, **kwargs): + if not isinstance(type, int): + raise TypeError("event type must be an integer") + if not 0 <= type < NUMEVENTS: - raise error("event type out of range") - dict_ = dict_ if dict_ is not None else {} - dict_.update(kwargs) + raise ValueError("event type out of range") + + dict = dict if dict is not None else {} + dict.update(kwargs) - if "type" in dict_: - raise error("redundant type field in event dict") + if "type" in dict: + raise ValueError("redundant type field in event dict") - dict_["type"] = type + self._type = type + self._dict = dict - self.__dict__ = dict_ + def __new__(cls, *args, **kwargs): + if "type" in kwargs: + raise ValueError("redundant type field in event dict") + return super().__new__(cls) def __int__(self): return self.type @@ -130,14 +138,28 @@ def __repr__(self): @property def dict(self): - return self.__dict__ + return self._dict + + @property + def type(self): + return self._type + + def __getattr__(self, name): + return self._dict[name] + + def __getattribute__(self, name): + if name == "__dict__": + return super().__getattribute__("_dict") + return super().__getattribute__(name) - @dict.setter - def dict(self, value: dict[str, ...]): - self.__dict__ = value + def __setattr__(self, name, value): + if name in ("_type", "_dict", "type", "dict"): + return super().__setattr__(name, value) + self._dict[name] = value EventType = Event +register_event_class(Event) def init(): From 097ad6a0e2327791080502ebb377dc5bc1733a53 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:25:39 +0200 Subject: [PATCH 10/13] Moving Event() to python - bugfix 3. --- src_c/_event.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src_c/_event.c b/src_c/_event.c index 98616125df..4a5a4c70ec 100644 --- a/src_c/_event.c +++ b/src_c/_event.c @@ -1844,8 +1844,10 @@ pg_event_post(PyObject *self, PyObject *obj) if (PyErr_Occurred()) return NULL; - switch (pg_post_event(e.type, e.dict)) { - pgEvent_FreeEventData(e); + int res = pg_post_event(e.type, e.dict); + pgEvent_FreeEventData(e); + + switch (res) { case 0: Py_RETURN_FALSE; case 1: From 931cf5efb04ee08462590f7a2f08aa0e1e6ddb74 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:56:48 +0200 Subject: [PATCH 11/13] Moving Event() to python - bugfix 4. --- buildconfig/stubs/pygame/_common.pyi | 21 ++++++++++++++++++++- buildconfig/stubs/pygame/_event.pyi | 13 +++++++------ buildconfig/stubs/pygame/event.pyi | 18 +++--------------- src_py/event.py | 2 ++ 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/buildconfig/stubs/pygame/_common.pyi b/buildconfig/stubs/pygame/_common.pyi index 19e958a724..690b17139a 100644 --- a/buildconfig/stubs/pygame/_common.pyi +++ b/buildconfig/stubs/pygame/_common.pyi @@ -1,5 +1,5 @@ from os import PathLike -from typing import IO, Callable, Tuple, Union, TypeVar +from typing import IO, Callable, Tuple, Union, TypeVar, Dict, Any, Optional from typing_extensions import Literal as Literal, SupportsIndex as SupportsIndex from typing_extensions import Protocol @@ -22,6 +22,25 @@ class Sequence(Protocol[_T]): def __getitem__(self, __i: SupportsIndex) -> _T: ... def __len__(self) -> int: ... + +class EventLike(Protocol): + # __dict__: Dict[str, Any] + def __init__( + self, type: int, dict: Optional[Dict[str, Any]] = None, **kwargs: Any + ) -> None: ... + def __new__(cls, *args, **kwargs) -> "EventLike": ... + def __getattribute__(self, name: str) -> Any: ... + def __setattr__(self, name: str, value: Any) -> None: ... + def __delattr__(self, name: str) -> None: ... + def __int__(self) -> int: ... + def __bool__(self) -> bool: ... + def __eq__(self, other) -> bool: ... + + @property + def type(self) -> int: ... + @property + def dict(self) -> Dict[str, Any]: ... + # Right now, it isn't possible to annotate sizes (popular tools don't support it) but # when it is, the below types should be appropriately annotated diff --git a/buildconfig/stubs/pygame/_event.pyi b/buildconfig/stubs/pygame/_event.pyi index 237557f21a..03d6076c63 100644 --- a/buildconfig/stubs/pygame/_event.pyi +++ b/buildconfig/stubs/pygame/_event.pyi @@ -3,9 +3,10 @@ from typing import ( List, Optional, Union, + Type, ) -from ._common import Sequence +from ._common import Sequence, EventLike _EventTypes = Union[int, Sequence[int]] @@ -14,9 +15,9 @@ def get( eventtype: Optional[_EventTypes] = None, pump: Any = True, exclude: Optional[_EventTypes] = None, -) -> List[Event]: ... -def poll() -> Event: ... -def wait(timeout: int = 0) -> Event: ... +) -> List[EventLike]: ... +def poll() -> EventLike: ... +def wait(timeout: int = 0) -> EventLike: ... def peek(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> bool: ... def clear(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> None: ... def set_blocked(type: Optional[_EventTypes], /) -> None: ... @@ -24,5 +25,5 @@ def set_allowed(type: Optional[_EventTypes], /) -> None: ... def get_blocked(type: _EventTypes, /) -> bool: ... def set_grab(grab: bool, /) -> None: ... def get_grab() -> bool: ... -def post(event: Event, /) -> bool: ... -def register_event_class(cls: type): ... +def post(event: EventLike, /) -> bool: ... +def register_event_class(cls: Type[EventLike]): ... diff --git a/buildconfig/stubs/pygame/event.pyi b/buildconfig/stubs/pygame/event.pyi index 9f4bd597ac..7a73c6ea6c 100644 --- a/buildconfig/stubs/pygame/event.pyi +++ b/buildconfig/stubs/pygame/event.pyi @@ -4,24 +4,12 @@ from typing import ( List, Optional, Union, - final, ) -from ._common import Sequence +from ._common import Sequence, EventLike -@final -class Event: - type: int - dict: Dict[str, Any] - __dict__: Dict[str, Any] - __hash__: None # type: ignore - def __init__( - self, type: int, dict: Dict[str, Any] = ..., **kwargs: Any - ) -> None: ... - def __getattribute__(self, name: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __delattr__(self, name: str) -> None: ... - def __bool__(self) -> bool: ... +class Event(EventLike): + ... _EventTypes = Union[int, Sequence[int]] diff --git a/src_py/event.py b/src_py/event.py index b04b3ec61a..69d539e485 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -131,6 +131,8 @@ def __bool__(self): return self.type != pg.NOEVENT def __eq__(self, other: Event): + if not isinstance(other, Event): + return NotImplemented return self.type == other.type and self.dict == other.dict def __repr__(self): From db570bef4144d1db1d4ba392703050d4efba0ab5 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Fri, 19 Jul 2024 22:32:36 +0200 Subject: [PATCH 12/13] Moving Event() to python - bugfix 5. --- src_py/event.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src_py/event.py b/src_py/event.py index 69d539e485..97b031e8c8 100644 --- a/src_py/event.py +++ b/src_py/event.py @@ -1,6 +1,6 @@ from __future__ import annotations -from pygame._event import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] +from pygame._event import * # pylint: disable=wildcard-import,unused-wildcard-import; lgtm[py/polluting-import] from pygame._event import _internal_mod_init as _init, _internal_mod_quit as _quit from pygame.constants import USEREVENT, NUMEVENTS from pygame.base import error @@ -156,8 +156,9 @@ def __getattribute__(self, name): def __setattr__(self, name, value): if name in ("_type", "_dict", "type", "dict"): - return super().__setattr__(name, value) - self._dict[name] = value + super().__setattr__(name, value) + else: + self._dict[name] = value EventType = Event From 06b8a145579e211111fa2ce3000297c6c4cc2648 Mon Sep 17 00:00:00 2001 From: polastyn <78505251+gresm@users.noreply.github.com> Date: Fri, 19 Jul 2024 23:24:41 +0200 Subject: [PATCH 13/13] Add documentation. --- docs/reST/c_api/event.rst | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/reST/c_api/event.rst b/docs/reST/c_api/event.rst index 7f053faf3d..5f36b4850f 100644 --- a/docs/reST/c_api/event.rst +++ b/docs/reST/c_api/event.rst @@ -13,25 +13,32 @@ The extension module :py:mod:`pygame.event`. Header file: src_c/include/pygame.h +.. c:type:: pgEventData -.. c:type:: pgEventObject - - The :py:class:`pygame.event.EventType` object C struct. + Struct holding information about the event object. .. c:member:: int type The event type code. + + .. c:member:: PyObject* dict + + Dict object of the event, might be NULL. + +.. c:function:: PyObject* pgEvent_GetType(void) -.. c:type:: pgEvent_Type + Return a python class that is currently set to be the event class - The pygame event object type :py:class:`pygame.event.EventType`. + If the class is not known at the time (called before ``pygame._event.register_event_class``) + this function will return NULL and set the error. .. c:function:: int pgEvent_Check(PyObject *x) Return true if *x* is a pygame event instance Will return false if *x* is a subclass of event. - This is a macro. No check is made that *x* is not ``NULL``. + Will return -1 if python error is set while checking. + No check is made that *x* is not ``NULL``. .. c:function:: PyObject* pgEvent_New(SDL_Event *event) @@ -39,6 +46,25 @@ Header file: src_c/include/pygame.h If *event* is ``NULL`` then create an empty event object. On failure raise a Python exception and return ``NULL``. +.. c:function:: PyObject* pgEvent_FromEventData(pgEventData) + + Return an event object constructed from pgEventData struct. + + On error returns NULL and sets python exception. + +.. c:function:: pgEventData pgEvent_GetEventData(PyObject *) + + Return a pgEventData struct containing information about event extracted from the python object. + + Beware: on error this doesn't retun any special sentiel value if error ocurred, only sets python exception, so use ``PyErr_Ocurred()`` for error checking. + Remember to call :c:func:`pgEvent_FreeEventData` after usage to avoid memory leaks. + +.. c:function:: void pgEvent_FreeEventData(pgEventData) + + Free resources held by pgEventData (decrefs dict). + + .. ## pgEvent_FreeEventData ## + .. c:function:: char* pgEvent_GetKeyDownInfo(void) Return an array of bools (using char) of length SDL_NUM_SCANCODES