furr@mdavcr.UUCP (Steven Furr) (05/30/91)
I would like to know if there is any way of providing Xt Event handlers to handle events that come from X extensions. The event type of these events is not known until the extension is initialized, and the event cannot be selected with XSelectInput. I would like to access the multibuffering extension in order to use the following technique for animation: void Canvas::realized( void ) { . . . XtAddEventHandler( widget(), 0, TRUE, Canvas::event_handler, (XtPointer)this ) // Select UpdateNotify events for each buffer attributes.mask = MultibufferUpdateNotifyMask; for (int i = 0; i < num_bufs; i++ ) XmbufChangeBufferAttributes( dpy, buffer[i], MultibufferEventMask, &attributes ); } void Canvas::event_handler( Widget w, XtPointer client_data, XEvent * ev ) { if ( event->type == MultibufferExt::event_base + UpdateNotify ) { Canvas * canvas = (Canvas *)client_data; int delay = 100; // milliseconds canvas->cycle_buffer( delay ); } } The problem is that Xt doesn't seem capable of dispatching any nonmaskable events to the event handler other than GraphicsExpose, NoExpose, MappingNotify, SelectionClear, SelectionRequest, SelectionNotify, and ClientMessage (as per p. 225 of O'Reilly vol. 4). Shouldn't event types outside the range of the X standard protocol be considered nonmaskable events by Xt? (i.e. those that get assigned to extension events) Since this appears not to be the case is there any possibility that this will change with X11.R5? Looking at the sample implementation, it seems that all that would be required would be to check if eventType is greater than LASTEvent in ConvertTypeToMask (in fact without this the current behaviour is not guaranteed to be correct) and set up appropriate defaults (i.e. mask=0, grabType=pass). The relevant sections of code follow: static Boolean DecideToDispatch(event) XEvent *event; { register Widget widget; EventMask mask; GrabType grabType; Widget dspWidget; Time time = 0; XtPerDisplay pd; XtPerDisplayInput pdi; XtGrabList grabList; widget = XtWindowToWidget (event->xany.display, event->xany.window); pd = _XtGetPerDisplay(event->xany.display); pdi = _XtGetPerDisplayInput(event->xany.display); grabList = *_XtGetGrabList(pdi); /* Lint complains about &grabType not matching the declaration. Don't bother trying to fix it, it won't work */ ConvertTypeToMask(event->xany.type, &mask, &grabType); switch (event->xany.type) { case KeyPress: case KeyRelease: time = event->xkey.time; break; case ButtonPress: case ButtonRelease: time = event->xbutton.time; break; case MotionNotify: time = event->xmotion.time; break; case EnterNotify: case LeaveNotify: time = event->xcrossing.time; break; case PropertyNotify: time = event->xproperty.time; break; case SelectionClear: time = event->xselectionclear.time; break; } if (time) pd->last_timestamp = time; if (widget == NULL) { if (grabType != remap) return False; /* event occurred in a non-widget window, but we've promised also to dispatch it to the nearest accessible spring_loaded widget */ else if ((widget = LookupSpringLoaded(grabList)) != NULL) return DispatchEvent(event, widget, mask, pd); return False; } switch(grabType) { case pass: return DispatchEvent(event, widget, mask, pd); case ignore: if ((grabList == NULL || _XtOnGrabList(widget,grabList)) && XtIsSensitive(widget)) { return DispatchEvent(event, widget, mask, pd); } return False; case remap: { Boolean was_dispatched = False; extern Widget _XtFindRemapWidget(); extern void _XtUngrabBadGrabs(); dspWidget = _XtFindRemapWidget(event, widget, mask, pdi); if ((grabList == NULL || _XtOnGrabList(dspWidget, grabList)) && XtIsSensitive(dspWidget)) { was_dispatched = DispatchEvent(event, dspWidget, mask, pd); } else _XtUngrabBadGrabs(event, widget, mask, pdi); /* Also dispatch to nearest accessible spring_loaded. */ /* Fetch this afterward to reflect modal list changes */ grabList = *_XtGetGrabList(pdi); widget = LookupSpringLoaded(grabList); if (widget != NULL && widget != dspWidget) { was_dispatched |= DispatchEvent(event, widget, mask, pd); } return was_dispatched; } } /* should never reach here */ return False; } typedef enum _GrabType {pass, ignore, remap} GrabType; static void ConvertTypeToMask (eventType, mask, grabType) int eventType; EventMask *mask; GrabType *grabType; { static Const struct { EventMask mask; GrabType grabType; } masks[] = { {0, pass}, /* shouldn't see 0 */ {0, pass}, /* shouldn't see 1 */ {KeyPressMask, remap}, /* KeyPress */ {KeyReleaseMask, remap}, /* KeyRelease */ {ButtonPressMask, remap}, /* ButtonPress */ {ButtonReleaseMask, remap}, /* ButtonRelease */ {PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask, ignore}, /* MotionNotify */ {EnterWindowMask, ignore}, /* EnterNotify */ {LeaveWindowMask, pass}, /* LeaveNotify */ {FocusChangeMask, pass}, /* FocusIn */ {FocusChangeMask, pass}, /* FocusOut */ {KeymapStateMask, pass}, /* KeymapNotify */ {ExposureMask, pass}, /* Expose */ {0, pass}, /* GraphicsExpose */ {0, pass}, /* NoExpose */ {VisibilityChangeMask, pass}, /* VisibilityNotify */ {SubstructureNotifyMask, pass}, /* CreateNotify */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* DestroyNotify */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* UnmapNotify */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* MapNotify */ {SubstructureRedirectMask, pass}, /* MapRequest */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* ReparentNotify */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* ConfigureNotify */ {SubstructureRedirectMask, pass}, /* ConfigureRequest */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* GravityNotify */ {ResizeRedirectMask, pass}, /* ResizeRequest */ {StructureNotifyMask | SubstructureNotifyMask, pass}, /* CirculateNotify */ {SubstructureRedirectMask, pass}, /* CirculateRequest */ {PropertyChangeMask, pass}, /* PropertyNotify */ {0, pass}, /* SelectionClear */ {0, pass}, /* SelectionRequest */ {0, pass}, /* SelectionNotify */ {ColormapChangeMask, pass}, /* ColormapNotify */ {0, pass}, /* ClientMessage */ {0, pass}, /* MappingNotify */ }; eventType &= 0x7f; /* Events sent with XSendEvent have high bit set. */ (*mask) = masks[eventType].mask; (*grabType) = masks[eventType].grabType; } -- Steve Furr ( furr@mda.ca ) Lesser artists borrow, great artists steal. - blatantly stolen from Igor Stravinsky
rthomson@mesa.dsd.es.com (Rich Thomson) (05/30/91)
In article <1224@mdavcr.UUCP> furr@mdavcr.UUCP (Steven Furr) writes: >I would like to know if there is any way of providing Xt Event handlers >to handle events that come from X extensions. The event type of these >events is not known until the extension is initialized, and the event >cannot be selected with XSelectInput. > [...] > >The problem is that Xt doesn't seem capable of dispatching any nonmaskable >events to the event handler other than GraphicsExpose, NoExpose, >MappingNotify, SelectionClear, SelectionRequest, SelectionNotify, and >ClientMessage (as per p. 225 of O'Reilly vol. 4). > >Shouldn't event types outside the range of the X standard protocol be >considered nonmaskable events by Xt? (i.e. those that get assigned to >extension events) > >Since this appears not to be the case is there any possibility that this >will change with X11.R5? I have been discussing this with Ralph Swick at MIT. There was some talk in this newsgroup earlier about dealing with such problems for the input extension. The problem is that the Intrinsics are generally extension-illiterate, unlike Xlib. I think it was initially thought that most extensions wouldn't generate events, but this isn't a very good assumption. E&S' custom PEX picking extension generates events, the X Input Extension (in the R5 release) generates events, etc. In general, I think not only this problem with event handlers needs to be addressed, but the larger problem of event management in general. Most of the work is getting the Translation Manager to be literate of extensions. A workable minimum is some version of the TM that is at least literate of the Input Extension for R5. The problem is a sticky one indeed. Unfortunately, I can't comment (yet) on your proposed change to the sample implementation because I haven't the time to learn the internals of the Toolkit. Maybe in the summer (yeah, right! :). -- Rich -- ``Read my MIPS -- no new VAXes!!'' -- George Bush after sniffing freon Disclaimer: I speak for myself, except as noted. UUCP: ...!uunet!dsd.es.com!rthomson Rich Thomson ARPA: rthomson@dsd.es.com PEXt Programmer
rws@expo.lcs.mit.EDU (Bob Scheifler) (05/30/91)
I would like to know if there is any way of providing Xt Event handlers to handle events that come from X extensions. Nope. It's a travesty that this issue has not yet been properly addressed. Shouldn't event types outside the range of the X standard protocol be considered nonmaskable events by Xt? (i.e. those that get assigned to extension events) No, I don't think so, lumping everything together is rather undesirable. There's no particularly good reason why my selection event handlers should be inundated with input device extension motion notify events, for example. The nonmaskable approach is flawed to begin with; I think a better approach is to think about associating handlers with specific event type codes. But there are a number of issues to consider to do things "right". Since this appears not to be the case is there any possibility that this will change with X11.R5? It's not likely that your approach will be adopted. There is some slim chance that some kind of support, perhaps only experimental in nature, might work its way into R5.
swick@athena.mit.EDU (Ralph Swick) (05/30/91)
I would like to know if there is any way of providing Xt Event handlers to handle events that come from X extensions. Unfortunately no, not at the present time. The event type of these events is not known until the extension is initialized, and the event cannot be selected with XSelectInput. Correct. This is only one of the difficulties involved in adding such support. The problem is that Xt doesn't seem capable of dispatching any nonmaskable events to the event handler other than GraphicsExpose, NoExpose, MappingNotify, SelectionClear, SelectionRequest, SelectionNotify, and ClientMessage Also correct. These are very explicitly specified to be the [only] events referred to by the 'nonmaskable' argument to XtAddEventHandler. Actually, MappingNotify is a mistake; see below. Shouldn't event types outside the range of the X standard protocol be considered nonmaskable events by Xt? Perhaps but that would now be a significant backwards-incompatible specification change and is therefore not acceptable. An additional difficulty is that it is not correct to assume (or require) that all extension events have usable 'window' fields. MappingNotify is the only core event that doesn't contain a window and it requires quite a bit of internal manipulation in Xt to dispatch it reasonably. An aside; rather than "fixing" the implementation to dispatch MappingNotify to all event handlers registered with nonmaskable==True, we propose to change the spec to remove this event from the 'nonmaskable' list. As of R4, it is possible to express interest in MappingNotify through the translation table mechanism and this appears adequate. My own personal belief is that full extension event support in Xt should allow a widget to register interest in any event, not just those containing windows. Extension events should also be supported both through translation tables and through the more primitive event handler mechanism. Getting events dispatched to the right place is only half the problem; the other half (and the harder one, it appears to me) is requesting them from the server in the first place. is there any possibility that this will change with X11.R5? I can pretty much guarantee that full extension event support will not appear in R5, sorry to say. No guarantees, but some "experimental" code might be included with the distribution. Looking at the sample implementation, it seems that all that would be required ... I hope I've convinced you that this is far from sufficient. Steve Furr ( furr@mda.ca ) Lesser artists borrow, great artists steal. - blatantly stolen from Igor Stravinsky and fools reinvent? :-)
asente@adobe.com (Paul Asente) (05/31/91)
In article <1224@mdavcr.UUCP> furr@mdavcr.UUCP (Steven Furr) writes: >I would like to know if there is any way of providing Xt Event handlers >to handle events that come from X extensions. The event type of these >events is not known until the extension is initialized, and the event >cannot be selected with XSelectInput. This is correct; Xt does not handle events from extensions. >Shouldn't event types outside the range of the X standard protocol be >considered nonmaskable events by Xt? (i.e. those that get assigned to >extension events) That would be a simple but not very helpful solution. The Xt working group prefers to come up with a solution that is more well integrated with the rest of the Intrinsics, particularly the translation manager. >Since this appears not to be the case is there any possibility that this >will change with X11.R5? Nope. What you have to do now is not use XtAppMainLoop or XtAppProcessEvent. XtAppMainLoop should be replaced with something like while (1) { XEvent ev; XtAppNextEvent(app, &ev); if (!XtDispatchEvent(&ev)) { /* Must be an extension event; dispatch it myself */ } } Note that because of a bug in the R4 Xt, this will not currently work, but it has been fixed in R5. The R4 XtDispatchEvent may croak if passed a non-standard event; you need to do something like while (1) { XEvent ev; XtAppNextEvent(app, &ev); if (/* ev is an extension event */) { /* Dispatch it myself */ } else { if (!XtDispatchEvent(&ev)) { /* Shouldn't normally happen */ } } } XtAppProcessEvent is more problematical. If you call it with a mask of XtIMAll or XtIMXEvent and it encounters an extension event, it will quietly drop the event on the floor (or possibly croak in XtDispatchEvent under R4). You need to do something like (exact details depend on why you're using XtAppProcessEvent instead of XtAppNextEvent and XtDispatchEvent): XtInputMask mask; mask = XtAppPending(app); if (mask & XtIMXEvent /* && I-want-to-handle-it-now */) { /* Get event and process as above */ mask &= !XtIMXEvent; /* mask it out */ } XtAppProcessEvent(app, mask); /* won't handle X events */ This problem with XtAppProcessEvent will not go away in R5. -paul asente asente@adobe.com ...decwrl!adobe!asente Ratz put a bucket of liquid in front of me. "I wanted a glass of docs, Ratz. What the hell is this?" I barked. "Motif don't fit in a glass anymore," he barked back. I looked at the liquid. It was totally opaque to me.
pete@iris49.biosym.COM (Pete Ware) (05/31/91)
I understand the need for having a clean solution that supports translations, selecting for events and dispatching events all working on multiple displays (remember, event numbers can change from display to display) is complicated, it's just that the current mechanism provides absolutely no way to deal with extension events in a normal dispatch loop! >> The problem is that Xt doesn't seem capable of dispatching any nonmaskable >> events to the event handler other than GraphicsExpose, NoExpose, >> MappingNotify, SelectionClear, SelectionRequest, SelectionNotify, and >> ClientMessage >Also correct. These are very explicitly specified to be the [only] >events referred to by the 'nonmaskable' argument to XtAddEventHandler. >Actually, MappingNotify is a mistake; see below. >> Shouldn't event types outside the range of the X standard protocol be >> considered nonmaskable events by Xt? >> >Perhaps but that would now be a significant backwards-incompatible >specification change and is therefore not acceptable. An additional >difficulty is that it is not correct to assume (or require) that >all extension events have usable 'window' fields. MappingNotify >is the only core event that doesn't contain a window and it requires >quite a bit of internal manipulation in Xt to dispatch it reasonably. > Could you at least make it possible to handle non-recognized events instead of just discarding them? When I first started looking into this I initially (and incorrectly) assumed that adding a raw event handler and setting non-maskable to True, I'd get all the extension events passed to this handler. It made sense, since one cannont select for the extension event and any handlers for non-maskable events certainly have to check the event type in any case, but it didn't work. >An aside; rather than "fixing" the implementation to dispatch >MappingNotify to all event handlers registered with nonmaskable==True, >we propose to change the spec to remove this event from the 'nonmaskable' >list. As of R4, it is possible to express interest in MappingNotify >through the translation table mechanism and this appears adequate. It seems that removing MappingNotify from the list of nonmaskable events is a far more serious a change than dispatching additional events to handlers for nonmaskable events. After all, handlers for nonmaskable events already should handle GraphicsExpose, NoExpose, SelectionClear, SelectionRequest, SelectionNotify, ClientMessage and MappingNotify. >I hope I've convinced you that this is far from sufficient. I'm begging for minimal support so I don't have to force every application that wants to use an extension to write it's own private dispatch loop! I can live without the ultimate solution, but life is hard with the current situation. --pete Pete Ware / Biosym / San Diego CA / (619) 546-5532 email: pete@biosym.com
rws@expo.lcs.mit.EDU (Bob Scheifler) (05/31/91)
It seems that removing MappingNotify from the list of nonmaskable events is a far more serious a change than dispatching additional events to handlers for nonmaskable events. Hardly, given that no implementation of Xt (to my knowledge) has ever actually supported dispatching of MappingNotify in this way. (The MIT implementation sometimes dispatched to one window, that window being the contents of an uninitialized variable.)
swick@athena.mit.EDU (Ralph Swick) (05/31/91)
I'm begging for minimal support We hear you.