I was thinking the same, but mostly because I don't want to write a multi-line text edit control, which is a huge PITA. :p All of Spine is rendered with OpenGL, so all the UI widgets are custom built. Users can always look up a game script by name and execute it.
Your screenshot looks good except I don't think there should be a visibility dot, only a key dot (green if not key is set on current frame, red if keyed on current frame). I'm not yet sure about grouping the events node.
In the dopesheet we currently have a number of bone groups, and each has a number of timelines, one for each bone property that has a key. For events, we'd have a single "Events" group which would have a timeline under it for each named event that has a key. A timeline for each is needed to allow two events to be keyed on the same frame.
I think that about covers it for the whole feature from start to finish. 🙂 The dopesheet is the hardest part, it is quite complex.
Oh, I forgot that all the runtimes need callbacks. Animations are stateless and currently just take a time and pose the skeleton at that time. This isn't enough to fire callbacks. 🙁 We could change the API to take a "last time" and "new time" so that we know to fire callbacks between those. But, how does the animation fire the callback? It knows the skeleton (which you noted was important), animation, event, time the event was keyed, and time the event was fired.
Runtimes like spine-libgdx, spine-as3, and spine-csharp could store a listener list directly on Skeleton. For spine-c, since it is generic and using C function pointers is inconvenient for some implementations, I guess there could be a single, global callback function pointer. Implementations can use this to route the event appropriately. Skeleton should probably have a "void* rendererObject", eg so cococs2d can find the scene graph node from the Skeleton* in order to fire ObjC listeners stored on the node.