Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!think.com!zaphod.mps.ohio-state.edu!van-bc!mdavcr!furr From: furr@mdavcr.UUCP (Steven Furr) Newsgroups: comp.windows.x Subject: Xt Intrinsics, extensions, and event handlers Keywords: Xt,X extensions,multibuffering,nonmaskable event handlers Message-ID: <1224@mdavcr.UUCP> Date: 29 May 91 21:38:32 GMT Distribution: na Organization: MacDonald Dettwiler, 13800 Commerce Parkway, Richmond, BC, Canada V6V 2J3 Lines: 226 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