diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index dd9a4600b0..f8905e12da 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -408,6 +408,7 @@ + @@ -631,6 +632,7 @@ NotUsing NotUsing + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 4260bfcd90..f3cd8ca92b 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -43,6 +43,7 @@ + @@ -326,6 +327,7 @@ + diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj index a80d0924ba..b5a5a49f4c 100644 --- a/VisualC-WinRT/SDL-UWP.vcxproj +++ b/VisualC-WinRT/SDL-UWP.vcxproj @@ -114,6 +114,7 @@ + @@ -316,6 +317,7 @@ NotUsing + diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 3a7f523d9f..59e786fc23 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -332,6 +332,7 @@ + @@ -521,6 +522,7 @@ NotUsing NotUsing + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 24579a58eb..d58f179c07 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -495,6 +495,9 @@ dynapi + + events + events @@ -998,6 +1001,9 @@ dynapi + + events + events diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index 7dda524100..2c12c8a5ce 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -1400,6 +1400,20 @@ extern SDL_DECLSPEC SDL_bool SDLCALL SDL_EventEnabled(Uint32 type); */ extern SDL_DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); +/** + * Get window associated with an event. + * + * \param event an event containing a `windowID`. + * + * \returns the associated window on success or NULL if there is none. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_PollEvent + * \sa SDL_WaitEvent + * \sa SDL_WaitEventTimeout + */ +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromEvent(const SDL_Event *event); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 38aad316a8..b81e437b0a 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -471,6 +471,7 @@ SDL3_0.0.0 { SDL_GetWindowBordersSize; SDL_GetWindowDisplayScale; SDL_GetWindowFlags; + SDL_GetWindowFromEvent; SDL_GetWindowFromID; SDL_GetWindowFullscreenMode; SDL_GetWindowICCProfile; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 004eee31cb..e096d67202 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -496,6 +496,7 @@ #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL #define SDL_GetWindowDisplayScale SDL_GetWindowDisplayScale_REAL #define SDL_GetWindowFlags SDL_GetWindowFlags_REAL +#define SDL_GetWindowFromEvent SDL_GetWindowFromEvent_REAL #define SDL_GetWindowFromID SDL_GetWindowFromID_REAL #define SDL_GetWindowFullscreenMode SDL_GetWindowFullscreenMode_REAL #define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6cdf7ff094..7c232e3170 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -516,6 +516,7 @@ SDL_DYNAPI_PROC(int,SDL_GetWindowAspectRatio,(SDL_Window *a, float *b, float *c) SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(float,SDL_GetWindowDisplayScale,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_WindowFlags,SDL_GetWindowFlags,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromEvent,(const SDL_Event *a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromID,(SDL_WindowID a),(a),return) SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetWindowFullscreenMode,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetWindowICCProfile,(SDL_Window *a, size_t *b),(a,b),return) diff --git a/src/events/SDL_categories.c b/src/events/SDL_categories.c new file mode 100644 index 0000000000..cd57c632f9 --- /dev/null +++ b/src/events/SDL_categories.c @@ -0,0 +1,228 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 Sam Lantinga + + 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" + +/* SDL event categories */ + +#include "SDL_events_c.h" +#include "SDL_categories_c.h" + +SDL_EventCategory SDL_GetEventCategory(Uint32 type) +{ + if (type >= SDL_EVENT_USER && type <= SDL_EVENT_LAST) { + return SDL_EVENTCATEGORY_USER; + } + else if (type >= SDL_EVENT_DISPLAY_FIRST && type <= SDL_EVENT_DISPLAY_LAST) { + return SDL_EVENTCATEGORY_DISPLAY; + } + else if (type >= SDL_EVENT_WINDOW_FIRST && type <= SDL_EVENT_WINDOW_LAST) { + return SDL_EVENTCATEGORY_WINDOW; + } + switch (type) { + default: + return SDL_SetError("Unknown event type"); + + case SDL_EVENT_KEYMAP_CHANGED: + case SDL_EVENT_TERMINATING: + case SDL_EVENT_LOW_MEMORY: + case SDL_EVENT_WILL_ENTER_BACKGROUND: + case SDL_EVENT_DID_ENTER_BACKGROUND: + case SDL_EVENT_WILL_ENTER_FOREGROUND: + case SDL_EVENT_DID_ENTER_FOREGROUND: + case SDL_EVENT_LOCALE_CHANGED: + case SDL_EVENT_SYSTEM_THEME_CHANGED: + case SDL_EVENT_RENDER_TARGETS_RESET: + case SDL_EVENT_RENDER_DEVICE_RESET: + return SDL_EVENTCATEGORY_SYSTEM; + + case SDL_EVENT_QUIT: + return SDL_EVENTCATEGORY_QUIT; + + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + return SDL_EVENTCATEGORY_KEY; + + case SDL_EVENT_TEXT_EDITING: + return SDL_EVENTCATEGORY_EDIT; + + case SDL_EVENT_TEXT_INPUT: + return SDL_EVENTCATEGORY_TEXT; + + case SDL_EVENT_KEYBOARD_ADDED: + case SDL_EVENT_KEYBOARD_REMOVED: + return SDL_EVENTCATEGORY_KDEVICE; + + case SDL_EVENT_TEXT_EDITING_CANDIDATES: + return SDL_EVENTCATEGORY_EDIT_CANDIDATES; + + case SDL_EVENT_MOUSE_MOTION: + return SDL_EVENTCATEGORY_MOTION; + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + return SDL_EVENTCATEGORY_BUTTON; + + case SDL_EVENT_MOUSE_WHEEL: + return SDL_EVENTCATEGORY_WHEEL; + + case SDL_EVENT_MOUSE_ADDED: + case SDL_EVENT_MOUSE_REMOVED: + return SDL_EVENTCATEGORY_MDEVICE; + + case SDL_EVENT_JOYSTICK_AXIS_MOTION: + return SDL_EVENTCATEGORY_JAXIS; + + case SDL_EVENT_JOYSTICK_BALL_MOTION: + return SDL_EVENTCATEGORY_JBALL; + + case SDL_EVENT_JOYSTICK_HAT_MOTION: + return SDL_EVENTCATEGORY_JHAT; + + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: + case SDL_EVENT_JOYSTICK_BUTTON_UP: + return SDL_EVENTCATEGORY_JBUTTON; + + case SDL_EVENT_JOYSTICK_ADDED: + case SDL_EVENT_JOYSTICK_REMOVED: + case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE: + return SDL_EVENTCATEGORY_JDEVICE; + + case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: + return SDL_EVENTCATEGORY_JBATTERY; + + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + return SDL_EVENTCATEGORY_GAXIS; + + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + return SDL_EVENTCATEGORY_GBUTTON; + + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + case SDL_EVENT_GAMEPAD_REMAPPED: + case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE: + case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED: + return SDL_EVENTCATEGORY_GDEVICE; + + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + return SDL_EVENTCATEGORY_GTOUCHPAD; + + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: + return SDL_EVENTCATEGORY_GSENSOR; + + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_MOTION: + return SDL_EVENTCATEGORY_TFINGER; + + case SDL_EVENT_CLIPBOARD_UPDATE: + return SDL_EVENTCATEGORY_CLIPBOARD; + + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + case SDL_EVENT_DROP_BEGIN: + case SDL_EVENT_DROP_COMPLETE: + case SDL_EVENT_DROP_POSITION: + return SDL_EVENTCATEGORY_DROP; + + case SDL_EVENT_AUDIO_DEVICE_ADDED: + case SDL_EVENT_AUDIO_DEVICE_REMOVED: + case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED: + return SDL_EVENTCATEGORY_ADEVICE; + + case SDL_EVENT_SENSOR_UPDATE: + return SDL_EVENTCATEGORY_SENSOR; + + case SDL_EVENT_PEN_DOWN: + case SDL_EVENT_PEN_UP: + return SDL_EVENTCATEGORY_PTIP; + + case SDL_EVENT_PEN_MOTION: + return SDL_EVENTCATEGORY_PMOTION; + + case SDL_EVENT_PEN_BUTTON_DOWN: + case SDL_EVENT_PEN_BUTTON_UP: + return SDL_EVENTCATEGORY_PBUTTON; + + case SDL_EVENT_CAMERA_DEVICE_ADDED: + case SDL_EVENT_CAMERA_DEVICE_REMOVED: + case SDL_EVENT_CAMERA_DEVICE_APPROVED: + case SDL_EVENT_CAMERA_DEVICE_DENIED: + return SDL_EVENTCATEGORY_CDEVICE; + } +} + +SDL_Window *SDL_GetWindowFromEvent(const SDL_Event *event) +{ + SDL_WindowID windowID; + + switch (SDL_GetEventCategory(event->type)) { + case SDL_EVENTCATEGORY_USER: + windowID = event->user.windowID; + break; + case SDL_EVENTCATEGORY_WINDOW: + windowID = event->window.windowID; + break; + case SDL_EVENTCATEGORY_KEY: + windowID = event->key.windowID; + break; + case SDL_EVENTCATEGORY_EDIT: + windowID = event->edit.windowID; + break; + case SDL_EVENTCATEGORY_TEXT: + windowID = event->text.windowID; + break; + case SDL_EVENTCATEGORY_EDIT_CANDIDATES: + windowID = event->edit_candidates.windowID; + break; + case SDL_EVENTCATEGORY_MOTION: + windowID = event->motion.windowID; + break; + case SDL_EVENTCATEGORY_BUTTON: + windowID = event->button.windowID; + break; + case SDL_EVENTCATEGORY_WHEEL: + windowID = event->wheel.windowID; + break; + case SDL_EVENTCATEGORY_TFINGER: + windowID = event->tfinger.windowID; + break; + case SDL_EVENTCATEGORY_PTIP: + windowID = event->ptip.windowID; + break; + case SDL_EVENTCATEGORY_PMOTION: + windowID = event->pmotion.windowID; + break; + case SDL_EVENTCATEGORY_PBUTTON: + windowID = event->pbutton.windowID; + break; + case SDL_EVENTCATEGORY_DROP: + windowID = event->drop.windowID; + break; + default: + /* < 0 -> invalid event type (error is set by SDL_GetEventCategory) */ + /* else -> event has no associated window (not an error) */ + return NULL; + } + return SDL_GetWindowFromID(windowID); +} diff --git a/src/events/SDL_categories_c.h b/src/events/SDL_categories_c.h new file mode 100644 index 0000000000..b184311fbf --- /dev/null +++ b/src/events/SDL_categories_c.h @@ -0,0 +1,66 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 Sam Lantinga + + 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" + +#ifndef SDL_categories_c_h_ +#define SDL_categories_c_h_ + +typedef enum SDL_EventCategory +{ + SDL_EVENTCATEGORY_SYSTEM, + SDL_EVENTCATEGORY_DISPLAY, + SDL_EVENTCATEGORY_WINDOW, + SDL_EVENTCATEGORY_KDEVICE, + SDL_EVENTCATEGORY_KEY, + SDL_EVENTCATEGORY_EDIT, + SDL_EVENTCATEGORY_EDIT_CANDIDATES, + SDL_EVENTCATEGORY_TEXT, + SDL_EVENTCATEGORY_MDEVICE, + SDL_EVENTCATEGORY_MOTION, + SDL_EVENTCATEGORY_BUTTON, + SDL_EVENTCATEGORY_WHEEL, + SDL_EVENTCATEGORY_JDEVICE, + SDL_EVENTCATEGORY_JAXIS, + SDL_EVENTCATEGORY_JBALL, + SDL_EVENTCATEGORY_JHAT, + SDL_EVENTCATEGORY_JBUTTON, + SDL_EVENTCATEGORY_JBATTERY, + SDL_EVENTCATEGORY_GDEVICE, + SDL_EVENTCATEGORY_GAXIS, + SDL_EVENTCATEGORY_GBUTTON, + SDL_EVENTCATEGORY_GTOUCHPAD, + SDL_EVENTCATEGORY_GSENSOR, + SDL_EVENTCATEGORY_ADEVICE, + SDL_EVENTCATEGORY_CDEVICE, + SDL_EVENTCATEGORY_SENSOR, + SDL_EVENTCATEGORY_QUIT, + SDL_EVENTCATEGORY_USER, + SDL_EVENTCATEGORY_TFINGER, + SDL_EVENTCATEGORY_PTIP, + SDL_EVENTCATEGORY_PMOTION, + SDL_EVENTCATEGORY_PBUTTON, + SDL_EVENTCATEGORY_DROP, + SDL_EVENTCATEGORY_CLIPBOARD, +} SDL_EventCategory; + +extern SDL_EventCategory SDL_GetEventCategory(Uint32 type); + +#endif /* SDL_categories_c_h_ */ diff --git a/test/testautomation_events.c b/test/testautomation_events.c index 14418f76cc..b7fae05d5c 100644 --- a/test/testautomation_events.c +++ b/test/testautomation_events.c @@ -22,6 +22,8 @@ static int g_eventFilterCalled = 0; static int g_userdataValue1 = 1; static int g_userdataValue2 = 2; +#define MAX_ITERATIONS 100 + /* Event filter that sets some flags and optionally checks userdata */ static int SDLCALL events_sampleNullEventFilter(void *userdata, SDL_Event *event) { @@ -45,31 +47,57 @@ static int SDLCALL events_sampleNullEventFilter(void *userdata, SDL_Event *event */ static int events_pushPumpAndPollUserevent(void *arg) { - SDL_Event event1; - SDL_Event event2; + SDL_Event event_in; + SDL_Event event_out; int result; + int i; + Sint32 ref_code = SDLTest_RandomSint32(); + SDL_Window *event_window; + + /* Flush all events */ + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); + SDLTest_AssertCheck(!SDL_HasEvents(SDL_EVENT_USER, SDL_EVENT_USER), "Check SDL_HasEvents returns false"); /* Create user event */ - event1.type = SDL_EVENT_USER; - event1.common.timestamp = 0; - event1.user.code = SDLTest_RandomSint32(); - event1.user.data1 = (void *)&g_userdataValue1; - event1.user.data2 = (void *)&g_userdataValue2; + event_in.type = SDL_EVENT_USER; + event_in.user.windowID = 0; + event_in.common.timestamp = 0; + event_in.user.code = ref_code; + event_in.user.data1 = (void *)&g_userdataValue1; + event_in.user.data2 = (void *)&g_userdataValue2; /* Push a user event onto the queue and force queue update */ - SDL_PushEvent(&event1); + SDL_PushEvent(&event_in); SDLTest_AssertPass("Call to SDL_PushEvent()"); SDL_PumpEvents(); SDLTest_AssertPass("Call to SDL_PumpEvents()"); - /* Poll for user event */ - result = SDL_PollEvent(&event2); - SDLTest_AssertPass("Call to SDL_PollEvent()"); - SDLTest_AssertCheck(result == 1, "Check result from SDL_PollEvent, expected: 1, got: %d", result); + SDLTest_AssertCheck(SDL_HasEvents(SDL_EVENT_USER, SDL_EVENT_USER), "Check SDL_HasEvents returns true"); + + /* Poll until we get a user event. */ + for (i = 0; i < MAX_ITERATIONS; i++) { + result = SDL_PollEvent(&event_out); + SDLTest_AssertPass("Call to SDL_PollEvent()"); + SDLTest_AssertCheck(result == 1, "Check result from SDL_PollEvent, expected: 1, got: %d", result); + if (!result) { + break; + } + if (event_out.type == SDL_EVENT_USER) { + break; + } + } + SDLTest_AssertCheck(i < MAX_ITERATIONS, "Check the user event is seen in less then %d polls, got %d poll", MAX_ITERATIONS, i + 1); + + SDLTest_AssertCheck(SDL_EVENT_USER == event_out.type, "Check event type is SDL_EVENT_USER, expected: 0x%x, got: 0x%" SDL_PRIx32, SDL_EVENT_USER, event_out.type); + SDLTest_AssertCheck(ref_code == event_out.user.code, "Check SDL_Event.user.code, expected: 0x%" SDL_PRIx32 ", got: 0x%" SDL_PRIx32 , ref_code, event_out.user.code); + SDLTest_AssertCheck(0 == event_out.user.windowID, "Check SDL_Event.user.windowID, expected: NULL , got: %" SDL_PRIu32, event_out.user.windowID); + SDLTest_AssertCheck((void *)&g_userdataValue1 == event_out.user.data1, "Check SDL_Event.user.data1, expected: %p, got: %p", (void *)&g_userdataValue1, event_out.user.data1); + SDLTest_AssertCheck((void *)&g_userdataValue2 == event_out.user.data2, "Check SDL_Event.user.data2, expected: %p, got: %p", (void *)&g_userdataValue2, event_out.user.data2); + event_window = SDL_GetWindowFromEvent(&event_out); + SDLTest_AssertCheck(NULL == SDL_GetWindowFromEvent(&event_out), "Check SDL_GetWindowFromEvent returns the window id from a user event, expected: NULL, got: %p", event_window); /* Need to finish getting all events and sentinel, otherwise other tests that rely on event are in bad state */ - while (SDL_PollEvent(&event2)) { - } + SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); return TEST_COMPLETED; } @@ -178,21 +206,24 @@ static int events_addDelEventWatchWithUserdata(void *arg) /* ================= Test References ================== */ /* Events test cases */ -static const SDLTest_TestCaseReference eventsTest1 = { - (SDLTest_TestCaseFp)events_pushPumpAndPollUserevent, "events_pushPumpAndPollUserevent", "Pushes, pumps and polls a user event", TEST_ENABLED +static const SDLTest_TestCaseReference eventsTest_pushPumpAndPollUserevent = { + events_pushPumpAndPollUserevent, "events_pushPumpAndPollUserevent", "Pushes, pumps and polls a user event", TEST_ENABLED }; -static const SDLTest_TestCaseReference eventsTest2 = { - (SDLTest_TestCaseFp)events_addDelEventWatch, "events_addDelEventWatch", "Adds and deletes an event watch function with NULL userdata", TEST_ENABLED +static const SDLTest_TestCaseReference eventsTest_addDelEventWatch = { + events_addDelEventWatch, "events_addDelEventWatch", "Adds and deletes an event watch function with NULL userdata", TEST_ENABLED }; -static const SDLTest_TestCaseReference eventsTest3 = { - (SDLTest_TestCaseFp)events_addDelEventWatchWithUserdata, "events_addDelEventWatchWithUserdata", "Adds and deletes an event watch function with userdata", TEST_ENABLED +static const SDLTest_TestCaseReference eventsTest_addDelEventWatchWithUserdata = { + events_addDelEventWatchWithUserdata, "events_addDelEventWatchWithUserdata", "Adds and deletes an event watch function with userdata", TEST_ENABLED }; /* Sequence of Events test cases */ static const SDLTest_TestCaseReference *eventsTests[] = { - &eventsTest1, &eventsTest2, &eventsTest3, NULL + &eventsTest_pushPumpAndPollUserevent, + &eventsTest_addDelEventWatch, + &eventsTest_addDelEventWatchWithUserdata, + NULL }; /* Events test suite (global) */