diff options
Diffstat (limited to 'libXt/src/Event.c')
-rw-r--r-- | libXt/src/Event.c | 3478 |
1 files changed, 1739 insertions, 1739 deletions
diff --git a/libXt/src/Event.c b/libXt/src/Event.c index 7be598787..9f4cb6cea 100644 --- a/libXt/src/Event.c +++ b/libXt/src/Event.c @@ -1,1739 +1,1739 @@ -/*********************************************************** -Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next -paragraph) shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -/* - -Copyright 1987, 1988, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "IntrinsicI.h" -#include "Shell.h" -#include "StringDefs.h" - -typedef struct _XtEventRecExt { - int type; - XtPointer select_data[1]; /* actual dimension is [mask] */ -} XtEventRecExt; - -#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type) -#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n]) - -#define NonMaskableMask ((EventMask)0x80000000L) - -/* - * These are definitions to make the code that handles exposure compresssion - * easier to read. - * - * COMP_EXPOSE - The compression exposure field of "widget" - * COMP_EXPOSE_TYPE - The type of compression (lower 4 bits of COMP_EXPOSE. - * GRAPHICS_EXPOSE - TRUE if the widget wants graphics expose events - * dispatched. - * NO_EXPOSE - TRUE if the widget wants No expose events dispatched. - */ - -#define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure) -#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f) -#define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \ - (XtExposeGraphicsExposeMerged & COMP_EXPOSE)) -#define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE) - -EventMask XtBuildEventMask( - Widget widget) -{ - XtEventTable ev; - EventMask mask = 0L; - WIDGET_TO_APPCON(widget); - - LOCK_APP(app); - for (ev = widget->core.event_table; ev != NULL; ev = ev->next) - if (ev->select) { - if (!ev->has_type_specifier) - mask |= ev->mask; - else { - if (EXT_TYPE(ev) < LASTEvent) { - Cardinal i; - for (i = 0; i < ev->mask; i++) - if (EXT_SELECT_DATA(ev, i)) - mask |= *(EventMask*)EXT_SELECT_DATA(ev, i); - } - } - } - LOCK_PROCESS; - if (widget->core.widget_class->core_class.expose != NULL) - mask |= ExposureMask; - if (widget->core.widget_class->core_class.visible_interest) - mask |= VisibilityChangeMask; - UNLOCK_PROCESS; - if (widget->core.tm.translations) - mask |= widget->core.tm.translations->eventMask; - - mask = mask & ~NonMaskableMask; - UNLOCK_APP(app); - return mask; -} - -static void CallExtensionSelector( - Widget widget, - ExtSelectRec* rec, - Boolean forceCall) -{ - XtEventRec* p; - XtPointer* data; - int* types; - Cardinal i, count = 0; - - for (p = widget->core.event_table; p != NULL; p = p->next) - if (p->has_type_specifier && - EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max) - count += p->mask; - - if (count == 0 && !forceCall) return; - - data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer)); - types = (int *) ALLOCATE_LOCAL(count * sizeof (int)); - count = 0; - - for (p = widget->core.event_table; p != NULL; p = p->next) - if (p->has_type_specifier && - EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max) - for (i =0; i < p->mask; i++) { - types[count] = EXT_TYPE(p); - data[count++] = EXT_SELECT_DATA(p, i); - } - - (*rec->proc)(widget, types, data, count, rec->client_data); - DEALLOCATE_LOCAL((char*) types); - DEALLOCATE_LOCAL((char*) data); -} - -static void -RemoveEventHandler( - Widget widget, - XtPointer select_data, - int type, - Boolean has_type_specifier, - Boolean other, - XtEventHandler proc, - XtPointer closure, - Boolean raw) -{ - XtEventRec *p, **pp; - EventMask eventMask, oldMask = XtBuildEventMask(widget); - - if (raw) raw = 1; - pp = &widget->core.event_table; - while ((p = *pp) && - (p->proc != proc || p->closure != closure || p->select == raw || - has_type_specifier != p->has_type_specifier || - (has_type_specifier && EXT_TYPE(p) != type))) - pp = &p->next; - if (!p) return; - - /* un-register it */ - if (!has_type_specifier) { - eventMask = *(EventMask*)select_data; - eventMask &= ~NonMaskableMask; - if (other) - eventMask |= NonMaskableMask; - p->mask &= ~eventMask; - } else { - Cardinal i; - /* p->mask specifies count of EXT_SELECT_DATA(p,i) - * search through the list of selection data, if not found - * dont remove this handler - */ - for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++; - if (i == p->mask) return; - if (p->mask == 1) p->mask = 0; - else { - p->mask--; - while (i < p->mask) { - EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1); - i++; - } - } - } - - if (!p->mask) { /* delete it entirely */ - *pp = p->next; - XtFree((char *)p); - } - - /* Reset select mask if realized and not raw. */ - if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) { - EventMask mask = XtBuildEventMask(widget); - Display* dpy = XtDisplay (widget); - - if (oldMask != mask) - XSelectInput(dpy, XtWindow(widget), mask); - - if (has_type_specifier) { - XtPerDisplay pd = _XtGetPerDisplay(dpy); - int i; - for (i = 0; i < pd->ext_select_count; i++) { - if (type >= pd->ext_select_list[i].min && - type <= pd->ext_select_list[i].max) { - CallExtensionSelector(widget, pd->ext_select_list+i, TRUE); - break; - } - if (type < pd->ext_select_list[i].min) break; - } - } - } -} - -/* Function Name: AddEventHandler - * Description: An Internal routine that does the actual work of - * adding the event handlers. - * Arguments: widget - widget to register an event handler for. - * eventMask - events to mask for. - * other - pass non maskable events to this proceedure. - * proc - proceedure to register. - * closure - data to pass to the event hander. - * position - where to add this event handler. - * force_new_position - If the element is already in the - * list, this will force it to the - * beginning or end depending on position. - * raw - If FALSE call XSelectInput for events in mask. - * Returns: none - */ - -static void -AddEventHandler( - Widget widget, - XtPointer select_data, - int type, - Boolean has_type_specifier, - Boolean other, - XtEventHandler proc, - XtPointer closure, - XtListPosition position, - Boolean force_new_position, - Boolean raw) -{ - register XtEventRec *p, **pp; - EventMask oldMask = 0, eventMask = 0; - - if (!has_type_specifier) { - eventMask = *(EventMask*)select_data & ~NonMaskableMask; - if (other) eventMask |= NonMaskableMask; - if (!eventMask) return; - } else if (!type) return; - - if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget); - - if (raw) raw = 1; - pp = &widget->core.event_table; - while ((p = *pp) && - (p->proc != proc || p->closure != closure || p->select == raw || - has_type_specifier != p->has_type_specifier || - (has_type_specifier && EXT_TYPE(p) != type))) - pp = &p->next; - - if (!p) { /* New proc to add to list */ - if (has_type_specifier) { - p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) + - sizeof(XtEventRecExt)); - EXT_TYPE(p) = type; - EXT_SELECT_DATA(p,0) = select_data; - p->mask = 1; - p->has_type_specifier = True; - } else { - p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec)); - p->mask = eventMask; - p->has_type_specifier = False; - } - p->proc = proc; - p->closure = closure; - p->select = ! raw; - - if (position == XtListHead) { - p->next = widget->core.event_table; - widget->core.event_table = p; - pp = &widget->core.event_table; - } else { - *pp = p; - p->next = NULL; - } - } - else { - if (force_new_position) { - *pp = p->next; - - if (position == XtListHead) { - p->next = widget->core.event_table; - widget->core.event_table = p; - } else { - /* - * Find the last element in the list. - */ - while (*pp) - pp = &(*pp)->next; - *pp = p; - p->next = NULL; - } - } - - if (!has_type_specifier) - p->mask |= eventMask; - else { - Cardinal i; - /* p->mask specifies count of EXT_SELECT_DATA(p,i) */ - for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); ) - i++; - if (i == p->mask) { - p = (XtEventRec*) XtRealloc((char*)p, - sizeof(XtEventRec) + - sizeof(XtEventRecExt) + - p->mask * sizeof(XtPointer)); - EXT_SELECT_DATA(p,i) = select_data; - p->mask++; - *pp = p; - } - } - } - - if (XtIsRealized(widget) && !raw) { - EventMask mask = XtBuildEventMask(widget); - Display* dpy = XtDisplay (widget); - - if (oldMask != mask) - XSelectInput(dpy, XtWindow(widget), mask); - - if (has_type_specifier) { - XtPerDisplay pd = _XtGetPerDisplay (dpy); - int i; - for (i = 0; i < pd->ext_select_count; i++) { - if (type >= pd->ext_select_list[i].min && - type <= pd->ext_select_list[i].max) { - CallExtensionSelector(widget, pd->ext_select_list+i, FALSE); - break; - } - if (type < pd->ext_select_list[i].min) break; - } - } - } -} - -void XtRemoveEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, - other, proc, closure, FALSE); - UNLOCK_APP(app); -} - -void XtAddEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, - proc, closure, XtListTail, FALSE, FALSE); - UNLOCK_APP(app); -} - -void XtInsertEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure, - XtListPosition position) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, - proc, closure, position, TRUE, FALSE); - UNLOCK_APP(app); -} - -void XtRemoveRawEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, - other, proc, closure, TRUE); - UNLOCK_APP(app); -} - -void XtInsertRawEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure, - XtListPosition position) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, - proc, closure, position, TRUE, TRUE); - UNLOCK_APP(app); -} - -void XtAddRawEventHandler( - Widget widget, - EventMask eventMask, - _XtBoolean other, - XtEventHandler proc, - XtPointer closure) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, - proc, closure, XtListTail, FALSE, TRUE); - UNLOCK_APP(app); -} - -void XtRemoveEventTypeHandler( - Widget widget, - int type, - XtPointer select_data, - XtEventHandler proc, - XtPointer closure) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - RemoveEventHandler(widget, select_data, type, TRUE, - FALSE, proc, closure, FALSE); - UNLOCK_APP(app); -} - -void XtInsertEventTypeHandler( - Widget widget, - int type, - XtPointer select_data, - XtEventHandler proc, - XtPointer closure, - XtListPosition position) -{ - WIDGET_TO_APPCON(widget); - LOCK_APP(app); - AddEventHandler(widget, select_data, type, TRUE, FALSE, - proc, closure, position, TRUE, FALSE); - UNLOCK_APP(app); -} - -typedef struct _WWPair { - struct _WWPair *next; - Window window; - Widget widget; -} *WWPair; - -typedef struct _WWTable { - unsigned int mask; /* size of hash table - 1 */ - unsigned int rehash; /* mask - 2 */ - unsigned int occupied; /* number of occupied entries */ - unsigned int fakes; /* number occupied by WWfake */ - Widget *entries; /* the entries */ - WWPair pairs; /* bogus entries */ -} *WWTable; - -static const WidgetRec WWfake; /* placeholder for deletions */ - -#define WWHASH(tab,win) ((win) & tab->mask) -#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1) -#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask) -#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable) - -static void ExpandWWTable(WWTable); - -void XtRegisterDrawable( - Display* display, - Drawable drawable, - Widget widget) -{ - WWTable tab; - int idx, rehash; - Widget entry; - Window window = (Window) drawable; - WIDGET_TO_APPCON(widget); - - LOCK_APP(app); - LOCK_PROCESS; - tab = WWTABLE(display); - if (window != XtWindow(widget)) { - WWPair pair; - pair = XtNew(struct _WWPair); - pair->next = tab->pairs; - pair->window = window; - pair->widget = widget; - tab->pairs = pair; - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; - } - if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) - ExpandWWTable(tab); - - idx = WWHASH(tab, window); - if ((entry = tab->entries[idx]) && entry != &WWfake) { - rehash = WWREHASHVAL(tab, window); - do { - idx = WWREHASH(tab, idx, rehash); - } while ((entry = tab->entries[idx]) && entry != &WWfake); - } - if (!entry) - tab->occupied++; - else if (entry == &WWfake) - tab->fakes--; - tab->entries[idx] = widget; - UNLOCK_PROCESS; - UNLOCK_APP(app); -} - -void XtUnregisterDrawable( - Display* display, - Drawable drawable) -{ - WWTable tab; - int idx, rehash; - Widget entry; - Window window = (Window) drawable; - Widget widget = XtWindowToWidget (display, window); - DPY_TO_APPCON(display); - - if (widget == NULL) return; - - LOCK_APP(app); - LOCK_PROCESS; - tab = WWTABLE(display); - if (window != XtWindow(widget)) { - WWPair *prev, pair; - - prev = &tab->pairs; - while ((pair = *prev) && pair->window != window) - prev = &pair->next; - if (pair) { - *prev = pair->next; - XtFree((char *)pair); - } - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; - } - idx = WWHASH(tab, window); - if ((entry = tab->entries[idx])) { - if (entry != widget) { - rehash = WWREHASHVAL(tab, window); - do { - idx = WWREHASH(tab, idx, rehash); - if (!(entry = tab->entries[idx])) { - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; - } - } while (entry != widget); - } - tab->entries[idx] = (Widget)&WWfake; - tab->fakes++; - } - UNLOCK_PROCESS; - UNLOCK_APP(app); -} - -static void ExpandWWTable( - register WWTable tab) -{ - unsigned int oldmask; - register Widget *oldentries, *entries; - register Cardinal oldidx, newidx, rehash; - register Widget entry; - - LOCK_PROCESS; - oldmask = tab->mask; - oldentries = tab->entries; - tab->occupied -= tab->fakes; - tab->fakes = 0; - if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) { - tab->mask = (tab->mask << 1) + 1; - tab->rehash = tab->mask - 2; - } - entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget)); - for (oldidx = 0; oldidx <= oldmask; oldidx++) { - if ((entry = oldentries[oldidx]) && entry != &WWfake) { - newidx = WWHASH(tab, XtWindow(entry)); - if (entries[newidx]) { - rehash = WWREHASHVAL(tab, XtWindow(entry)); - do { - newidx = WWREHASH(tab, newidx, rehash); - } while (entries[newidx]); - } - entries[newidx] = entry; - } - } - XtFree((char *)oldentries); - UNLOCK_PROCESS; -} - -Widget XtWindowToWidget( - register Display *display, - register Window window) -{ - register WWTable tab; - register int idx, rehash; - register Widget entry; - WWPair pair; - DPY_TO_APPCON(display); - - if (!window) return NULL; - - LOCK_APP(app); - LOCK_PROCESS; - tab = WWTABLE(display); - idx = WWHASH(tab, window); - if ((entry = tab->entries[idx]) && XtWindow(entry) != window) { - rehash = WWREHASHVAL(tab, window); - do { - idx = WWREHASH(tab, idx, rehash); - } while ((entry = tab->entries[idx]) && XtWindow(entry) != window); - } - if (entry) { - UNLOCK_PROCESS; - UNLOCK_APP(app); - return entry; - } - for (pair = tab->pairs; pair; pair = pair->next) { - if (pair->window == window) { - entry = pair->widget; - UNLOCK_PROCESS; - UNLOCK_APP(app); - return entry; - } - } - UNLOCK_PROCESS; - UNLOCK_APP(app); - return NULL; -} - -void _XtAllocWWTable( - XtPerDisplay pd) -{ - register WWTable tab; - - tab = (WWTable) __XtMalloc(sizeof(struct _WWTable)); - tab->mask = 0x7f; - tab->rehash = tab->mask - 2; - tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget)); - tab->occupied = 0; - tab->fakes = 0; - tab->pairs = NULL; - pd->WWtable = tab; -} - -void _XtFreeWWTable( - register XtPerDisplay pd) -{ - register WWPair pair, next; - - for (pair = pd->WWtable->pairs; pair; pair = next) { - next = pair->next; - XtFree((char *)pair); - } - XtFree((char *)pd->WWtable->entries); - XtFree((char *)pd->WWtable); -} - -#define EHMAXSIZE 25 /* do not make whopping big */ - -static Boolean CallEventHandlers( - Widget widget, - XEvent *event, - EventMask mask) -{ - register XtEventRec *p; - XtEventHandler *proc; - XtPointer *closure; - XtEventHandler procs[EHMAXSIZE]; - XtPointer closures[EHMAXSIZE]; - Boolean cont_to_disp = True; - int i, numprocs; - - /* Have to copy the procs into an array, because one of them might - * call XtRemoveEventHandler, which would break our linked list. */ - - numprocs = 0; - for (p=widget->core.event_table; p; p = p->next) { - if ((!p->has_type_specifier && (mask & p->mask)) || - (p->has_type_specifier && event->type == EXT_TYPE(p))) - numprocs++; - } - if (numprocs > EHMAXSIZE) { - proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) + - sizeof(XtPointer))); - closure = (XtPointer *)(proc + numprocs); - } else { - proc = procs; - closure = closures; - } - numprocs = 0; - for (p=widget->core.event_table; p; p = p->next) { - if ((!p->has_type_specifier && (mask & p->mask)) || - (p->has_type_specifier && event->type == EXT_TYPE(p))) { - proc[numprocs] = p->proc; - closure[numprocs] = p->closure; - numprocs++; - } - } -/* FUNCTIONS CALLED THROUGH POINTER proc: - Selection.c:ReqCleanup, - "Shell.c":EventHandler, - PassivGrab.c:ActiveHandler, - PassivGrab.c:RealizeHandler, - Keyboard.c:QueryEventMask, - _XtHandleFocus, - Selection.c:HandleSelectionReplies, - Selection.c:HandleGetIncrement, - Selection.c:HandleIncremental, - Selection.c:HandlePropertyGone, - Selection.c:HandleSelectionEvents - */ - for (i = 0; i < numprocs && cont_to_disp; i++) - (*(proc[i]))(widget, closure[i], event, &cont_to_disp); - if (numprocs > EHMAXSIZE) - XtFree((char *)proc); - return cont_to_disp; -} - -static void CompressExposures(XEvent *, Widget); - -#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\ - Button4MotionMask|Button5MotionMask) - -/* keep this SMALL to avoid blowing stack cache! */ -/* because some compilers allocate all local locals on procedure entry */ -#define EHSIZE 4 - -Boolean XtDispatchEventToWidget( - Widget widget, - XEvent* event) -{ - register XtEventRec *p; - Boolean was_dispatched = False; - Boolean call_tm = False; - Boolean cont_to_disp; - EventMask mask; - WIDGET_TO_APPCON(widget); - - LOCK_APP(app); - - mask = _XtConvertTypeToMask(event->type); - if (event->type == MotionNotify) - mask |= (event->xmotion.state & KnownButtons); - - LOCK_PROCESS; - if ( (mask == ExposureMask) || - ((event->type == NoExpose) && NO_EXPOSE) || - ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) { - - if (widget->core.widget_class->core_class.expose != NULL ) { - - /* We need to mask off the bits that could contain the information - * about whether or not we desire Graphics and NoExpose events. */ - - if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) || - (event->type == NoExpose) ) - - (*widget->core.widget_class->core_class.expose) - (widget, event, (Region)NULL); - else { - CompressExposures(event, widget); - } - was_dispatched = True; - } - } - - if ((mask == VisibilityChangeMask) && - XtClass(widget)->core_class.visible_interest) { - was_dispatched = True; - /* our visibility just changed... */ - switch (((XVisibilityEvent *)event)->state) { - case VisibilityUnobscured: - widget->core.visible = TRUE; - break; - - case VisibilityPartiallyObscured: - /* what do we want to say here? */ - /* well... some of us is visible */ - widget->core.visible = TRUE; - break; - - case VisibilityFullyObscured: - widget->core.visible = FALSE; - /* do we want to mark our children obscured? */ - break; - } - } - UNLOCK_PROCESS; - - /* to maintain "copy" semantics we check TM now but call later */ - if (widget->core.tm.translations && - (mask & widget->core.tm.translations->eventMask)) - call_tm = True; - - cont_to_disp = True; - p=widget->core.event_table; - if (p) { - if (p->next) { - XtEventHandler proc[EHSIZE]; - XtPointer closure[EHSIZE]; - int numprocs = 0; - - /* Have to copy the procs into an array, because one of them might - * call XtRemoveEventHandler, which would break our linked list. */ - - for (; p; p = p->next) { - if ((!p->has_type_specifier && (mask & p->mask)) || - (p->has_type_specifier && event->type == EXT_TYPE(p))) { - if (numprocs >= EHSIZE) - break; - proc[numprocs] = p->proc; - closure[numprocs] = p->closure; - numprocs++; - } - } - if (numprocs) { - if (p) { - cont_to_disp = CallEventHandlers(widget, event, mask); - } else { - int i; - for (i = 0; i < numprocs && cont_to_disp; i++) - (*(proc[i]))(widget, closure[i], event, &cont_to_disp); -/* FUNCTIONS CALLED THROUGH POINTER proc: - Selection.c:ReqCleanup, - "Shell.c":EventHandler, - PassivGrab.c:ActiveHandler, - PassivGrab.c:RealizeHandler, - Keyboard.c:QueryEventMask, - _XtHandleFocus, - Selection.c:HandleSelectionReplies, - Selection.c:HandleGetIncrement, - Selection.c:HandleIncremental, - Selection.c:HandlePropertyGone, - Selection.c:HandleSelectionEvents - */ - } - was_dispatched = True; - } - } else if ((!p->has_type_specifier && (mask & p->mask)) || - (p->has_type_specifier && event->type == EXT_TYPE(p))) { - (*p->proc)(widget, p->closure, event, &cont_to_disp); - was_dispatched = True; - } - } - if (call_tm && cont_to_disp) - _XtTranslateEvent(widget, event); - UNLOCK_APP(app); - return (was_dispatched|call_tm); -} - -/* - * This structure is passed into the check exposure proc. - */ - -typedef struct _CheckExposeInfo { - int type1, type2; /* Types of events to check for. */ - Boolean maximal; /* Ignore non-exposure events? */ - Boolean non_matching; /* Was there an event that did not - match either type? */ - Window window; /* Window to match. */ -} CheckExposeInfo; - -#define GetCount(ev) (((XExposeEvent *)(ev))->count) - -static void SendExposureEvent(XEvent *, Widget, XtPerDisplay); -static Bool CheckExposureEvent(Display *, XEvent *, char *); -static void AddExposureToRectangularRegion(XEvent *, Region); - -/* Function Name: CompressExposures - * Description: Handles all exposure compression - * Arguments: event - the xevent that is to be dispatched - * widget - the widget that this event occured in. - * Returns: none. - * - * NOTE: Event must be of type Expose or GraphicsExpose. - */ - -static void -CompressExposures( -XEvent * event, -Widget widget) -{ - CheckExposeInfo info; - int count; - Display* dpy = XtDisplay (widget); - XtPerDisplay pd = _XtGetPerDisplay(dpy); - XtEnum comp_expose; - XtEnum comp_expose_type; - Boolean no_region; - - LOCK_PROCESS; - comp_expose = COMP_EXPOSE; - UNLOCK_PROCESS; - comp_expose_type = comp_expose & 0x0f; - no_region = ((comp_expose & XtExposeNoRegion) ? True : False); - - if (no_region) - AddExposureToRectangularRegion(event, pd->region); - else - XtAddExposureToRegion(event, pd->region); - - if ( GetCount(event) != 0 ) - return; - - if ((comp_expose_type == XtExposeCompressSeries) || - (XEventsQueued(dpy, QueuedAfterReading) == 0)) { - SendExposureEvent(event, widget, pd); - return; - } - - if (comp_expose & XtExposeGraphicsExposeMerged) { - info.type1 = Expose; - info.type2 = GraphicsExpose; - } - else { - info.type1 = event->type; - info.type2 = 0; - } - info.maximal = (comp_expose_type == XtExposeCompressMaximal); - info.non_matching = FALSE; - info.window = XtWindow(widget); - -/* - * We have to be very careful here not to hose down the processor - * when blocking until count gets to zero. - * - * First, check to see if there are any events in the queue for this - * widget, and of the correct type. - * - * Once we cannot find any more events, check to see that count is zero. - * If it is not then block until we get another exposure event. - * - * If we find no more events, and count on the last one we saw was zero we - * we can be sure that all events have been processed. - * - * Unfortunately, we wind up having to look at the entire queue - * event if we're not doing Maximal compression, due to the - * semantics of XCheckIfEvent (we can't abort without re-ordering - * the event queue as a side-effect). - */ - - count = 0; - while (TRUE) { - XEvent event_return; - - if (XCheckIfEvent(dpy, &event_return, - CheckExposureEvent, (char *) &info)) { - - count = GetCount(&event_return); - if (no_region) - AddExposureToRectangularRegion(&event_return, pd->region); - else - XtAddExposureToRegion(&event_return, pd->region); - } - else if (count != 0) { - XIfEvent(dpy, &event_return, - CheckExposureEvent, (char *) &info); - count = GetCount(&event_return); - if (no_region) - AddExposureToRectangularRegion(&event_return, pd->region); - else - XtAddExposureToRegion(&event_return, pd->region); - } - else /* count == 0 && XCheckIfEvent Failed. */ - break; - } - - SendExposureEvent(event, widget, pd); -} - -void XtAddExposureToRegion( - XEvent *event, - Region region) -{ - XRectangle rect; - XExposeEvent *ev = (XExposeEvent *) event; - /* These Expose and GraphicsExpose fields are at identical offsets */ - - if (event->type == Expose || event->type == GraphicsExpose) { - rect.x = ev->x; - rect.y = ev->y; - rect.width = ev->width; - rect.height = ev->height; - XUnionRectWithRegion(&rect, region, region); - } -} - -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -static void AddExposureToRectangularRegion( - XEvent *event, /* when called internally, type is always appropriate */ - Region region) -{ - XRectangle rect; - XExposeEvent *ev = (XExposeEvent *) event; - /* These Expose and GraphicsExpose fields are at identical offsets */ - - rect.x = ev->x; - rect.y = ev->y; - rect.width = ev->width; - rect.height = ev->height; - - if (XEmptyRegion(region)) { - XUnionRectWithRegion(&rect, region, region); - } else { - XRectangle merged, bbox; - - XClipBox(region, &bbox); - merged.x = MIN(rect.x, bbox.x); - merged.y = MIN(rect.y, bbox.y); - merged.width = MAX(rect.x + rect.width, - bbox.x + bbox.width) - merged.x; - merged.height = MAX(rect.y + rect.height, - bbox.y + bbox.height) - merged.y; - XUnionRectWithRegion(&merged, region, region); - } -} - -static Region nullRegion; -/* READ-ONLY VARIABLES: nullRegion */ - -void _XtEventInitialize(void) -{ -#ifndef __lock_lint - nullRegion = XCreateRegion(); -#endif -} - -/* Function Name: SendExposureEvent - * Description: Sets the x, y, width, and height of the event - * to be the clip box of Expose Region. - * Arguments: event - the X Event to mangle; Expose or GraphicsExpose. - * widget - the widget that this event occured in. - * pd - the per display information for this widget. - * Returns: none. - */ - -static void -SendExposureEvent( -XEvent * event, -Widget widget, -XtPerDisplay pd) -{ - XtExposeProc expose; - XRectangle rect; - XtEnum comp_expose; - XExposeEvent *ev = (XExposeEvent *) event; - - XClipBox(pd->region, &rect); - ev->x = rect.x; - ev->y = rect.y; - ev->width = rect.width; - ev->height = rect.height; - - LOCK_PROCESS; - comp_expose = COMP_EXPOSE; - expose = widget->core.widget_class->core_class.expose; - UNLOCK_PROCESS; - if (comp_expose & XtExposeNoRegion) - (*expose)(widget, event, NULL); - else - (*expose)(widget, event, pd->region); - (void) XIntersectRegion(nullRegion, pd->region, pd->region); -} - -/* Function Name: CheckExposureEvent - * Description: Checks the event queue for an expose event - * Arguments: display - the display connection. - * event - the event to check. - * arg - a pointer to the exposure info structure. - * Returns: TRUE if we found an event of the correct type - * with the right window. - * - * NOTE: The only valid types (info.type1 and info.type2) are Expose - * and GraphicsExpose. - */ - -/* ARGSUSED */ -static Bool -CheckExposureEvent( -Display * disp, -XEvent * event, -char * arg) -{ - CheckExposeInfo * info = ((CheckExposeInfo *) arg); - - if ( (info->type1 == event->type) || (info->type2 == event->type)) { - if (!info->maximal && info->non_matching) return FALSE; - if (event->type == GraphicsExpose) - return(event->xgraphicsexpose.drawable == info->window); - return(event->xexpose.window == info->window); - } - info->non_matching = TRUE; - return(FALSE); -} - -static EventMask const masks[] = { - 0, /* Error, should never see */ - 0, /* Reply, should never see */ - KeyPressMask, /* KeyPress */ - KeyReleaseMask, /* KeyRelease */ - ButtonPressMask, /* ButtonPress */ - ButtonReleaseMask, /* ButtonRelease */ - PointerMotionMask /* MotionNotify */ - | ButtonMotionMask, - EnterWindowMask, /* EnterNotify */ - LeaveWindowMask, /* LeaveNotify */ - FocusChangeMask, /* FocusIn */ - FocusChangeMask, /* FocusOut */ - KeymapStateMask, /* KeymapNotify */ - ExposureMask, /* Expose */ - NonMaskableMask, /* GraphicsExpose, in GC */ - NonMaskableMask, /* NoExpose, in GC */ - VisibilityChangeMask, /* VisibilityNotify */ - SubstructureNotifyMask, /* CreateNotify */ - StructureNotifyMask /* DestroyNotify */ - | SubstructureNotifyMask, - StructureNotifyMask /* UnmapNotify */ - | SubstructureNotifyMask, - StructureNotifyMask /* MapNotify */ - | SubstructureNotifyMask, - SubstructureRedirectMask, /* MapRequest */ - StructureNotifyMask /* ReparentNotify */ - | SubstructureNotifyMask, - StructureNotifyMask /* ConfigureNotify */ - | SubstructureNotifyMask, - SubstructureRedirectMask, /* ConfigureRequest */ - StructureNotifyMask /* GravityNotify */ - | SubstructureNotifyMask, - ResizeRedirectMask, /* ResizeRequest */ - StructureNotifyMask /* CirculateNotify */ - | SubstructureNotifyMask, - SubstructureRedirectMask, /* CirculateRequest */ - PropertyChangeMask, /* PropertyNotify */ - NonMaskableMask, /* SelectionClear */ - NonMaskableMask, /* SelectionRequest */ - NonMaskableMask, /* SelectionNotify */ - ColormapChangeMask, /* ColormapNotify */ - NonMaskableMask, /* ClientMessage */ - NonMaskableMask /* MappingNotify */ -}; - -EventMask _XtConvertTypeToMask ( - int eventType) -{ - if ((Cardinal) eventType < XtNumber(masks)) - return masks[eventType]; - else - return NoEventMask; -} - -Boolean _XtOnGrabList( - register Widget widget, - XtGrabRec *grabList) -{ - register XtGrabRec* gl; - for (; widget != NULL; widget = (Widget)widget->core.parent) { - for (gl = grabList; gl != NULL; gl = gl->next) { - if (gl->widget == widget) return TRUE; - if (gl->exclusive) break; - } - } - return FALSE; -} - -static Widget LookupSpringLoaded( - XtGrabList grabList) -{ - XtGrabList gl; - - for (gl = grabList; gl != NULL; gl = gl->next) { - if (gl->spring_loaded) { - if (XtIsSensitive(gl->widget)) - return gl->widget; - else - return NULL; - } - if (gl->exclusive) break; - } - return NULL; -} - -static Boolean DispatchEvent( - XEvent* event, - Widget widget) -{ - - if (event->type == EnterNotify && - event->xcrossing.mode == NotifyNormal && - widget->core.widget_class->core_class.compress_enterleave) { - if (XPending(event->xcrossing.display)) { - XEvent nextEvent; - XPeekEvent(event->xcrossing.display, &nextEvent); - if (nextEvent.type == LeaveNotify && - event->xcrossing.window == nextEvent.xcrossing.window && - nextEvent.xcrossing.mode == NotifyNormal && - ((event->xcrossing.detail != NotifyInferior && - nextEvent.xcrossing.detail != NotifyInferior) || - (event->xcrossing.detail == NotifyInferior && - nextEvent.xcrossing.detail == NotifyInferior))) { - /* skip the enter/leave pair */ - XNextEvent(event->xcrossing.display, &nextEvent); - return False; - } - } - } - - if (event->type == MotionNotify && - widget->core.widget_class->core_class.compress_motion) { - while (XPending(event->xmotion.display)) { - XEvent nextEvent; - XPeekEvent(event->xmotion.display, &nextEvent); - if (nextEvent.type == MotionNotify && - event->xmotion.window == nextEvent.xmotion.window && - event->xmotion.subwindow == nextEvent.xmotion.subwindow) { - /* replace the current event with the next one */ - XNextEvent(event->xmotion.display, event); - } else break; - } - } - - return XtDispatchEventToWidget(widget, event); -} - -typedef enum _GrabType {pass, ignore, remap} GrabType; - -#if !defined(AIXV3) || !defined(AIXSHLIB) -static /* AIX shared libraries are broken */ -#endif -Boolean _XtDefaultDispatcher( - XEvent *event) -{ - register Widget widget; - GrabType grabType; - XtPerDisplayInput pdi; - XtGrabList grabList; - Boolean was_dispatched = False; - DPY_TO_APPCON(event->xany.display); - - /* the default dispatcher discards all extension events */ - if (event->type >= LASTEvent) - return False; - - LOCK_APP(app); - - switch (event->type) { - case KeyPress: - case KeyRelease: - case ButtonPress: - case ButtonRelease: grabType = remap; break; - case MotionNotify: - case EnterNotify: grabType = ignore; break; - default: grabType = pass; break; - } - - widget = XtWindowToWidget (event->xany.display, event->xany.window); - pdi = _XtGetPerDisplayInput(event->xany.display); - grabList = *_XtGetGrabList(pdi); - - if (widget == NULL) { - if (grabType == remap - && (widget = LookupSpringLoaded(grabList)) != NULL) { - /* event occurred in a non-widget window, but we've promised also - to dispatch it to the nearest accessible spring_loaded widget */ - was_dispatched = (XFilterEvent(event, XtWindow(widget)) - || XtDispatchEventToWidget(widget, event)); - } - else was_dispatched = XFilterEvent(event, None); - } - else if (grabType == pass) { - if (event->type == LeaveNotify || - event->type == FocusIn || - event->type == FocusOut) { - if (XtIsSensitive (widget)) - was_dispatched = (XFilterEvent(event, XtWindow(widget)) || - XtDispatchEventToWidget(widget, event)); - } else was_dispatched = (XFilterEvent(event, XtWindow(widget)) || - XtDispatchEventToWidget(widget, event)); - } - else if (grabType == ignore) { - if ((grabList == NULL || _XtOnGrabList(widget, grabList)) - && XtIsSensitive(widget)) { - was_dispatched = (XFilterEvent(event, XtWindow(widget)) - || DispatchEvent(event, widget)); - } - } - else if (grabType == remap) { - EventMask mask = _XtConvertTypeToMask(event->type); - Widget dspWidget; - Boolean was_filtered = False; - - dspWidget = _XtFindRemapWidget(event, widget, mask, pdi); - - if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList)) - && XtIsSensitive(dspWidget)) { - if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) { - /* If this event activated a device grab, release it. */ - _XtUngrabBadGrabs(event, widget, mask, pdi); - was_dispatched = True; - } else - was_dispatched = XtDispatchEventToWidget(dspWidget, event); - } - else _XtUngrabBadGrabs(event, widget, mask, pdi); - - if (!was_filtered) { - /* 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 = (XFilterEvent(event, XtWindow(widget)) - || XtDispatchEventToWidget(widget, event) - || was_dispatched); - } - } - } - UNLOCK_APP(app); - return was_dispatched; -} - -Boolean XtDispatchEvent ( - XEvent *event) -{ - Boolean was_dispatched, safe; - int dispatch_level; - int starting_count; - XtPerDisplay pd; - Time time = 0; - XtEventDispatchProc dispatch = _XtDefaultDispatcher; - XtAppContext app = XtDisplayToApplicationContext(event->xany.display); - - LOCK_APP(app); - dispatch_level = ++app->dispatch_level; - starting_count = app->destroy_count; - - switch (event->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; - - case MappingNotify: _XtRefreshMapping(event, True); break; - } - pd = _XtGetPerDisplay(event->xany.display); - if (time) pd->last_timestamp = time; - pd->last_event = *event; - - if (pd->dispatcher_list) { - dispatch = pd->dispatcher_list[event->type]; - if (dispatch == NULL) dispatch = _XtDefaultDispatcher; - } - was_dispatched = (*dispatch)(event); - - /* - * To make recursive XtDispatchEvent work, we need to do phase 2 destroys - * only on those widgets destroyed by this particular dispatch. - * - */ - - if (app->destroy_count > starting_count) - _XtDoPhase2Destroy(app, dispatch_level); - - app->dispatch_level = dispatch_level - 1; - - if ((safe = _XtSafeToDestroy(app))) { - if (app->dpy_destroy_count != 0) _XtCloseDisplays(app); - if (app->free_bindings) _XtDoFreeBindings(app); - } - UNLOCK_APP(app); - LOCK_PROCESS; - if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts(); - UNLOCK_PROCESS; - return was_dispatched; -} - -/* ARGSUSED */ -static void GrabDestroyCallback( - Widget widget, - XtPointer closure, - XtPointer call_data) -{ - /* Remove widget from grab list if it destroyed */ - XtRemoveGrab(widget); -} - -static XtGrabRec *NewGrabRec( - Widget widget, - Boolean exclusive, - Boolean spring_loaded) -{ - register XtGrabList gl; - - gl = XtNew(XtGrabRec); - gl->next = NULL; - gl->widget = widget; - gl->exclusive = exclusive; - gl->spring_loaded = spring_loaded; - - return gl; -} - -void XtAddGrab( - Widget widget, - _XtBoolean exclusive, - _XtBoolean spring_loaded) -{ - register XtGrabList gl; - XtGrabList *grabListPtr; - XtAppContext app = XtWidgetToApplicationContext(widget); - - LOCK_APP(app); - LOCK_PROCESS; - grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget))); - - if (spring_loaded && !exclusive) { - XtAppWarningMsg(app, - "grabError", "xtAddGrab", XtCXtToolkitError, - "XtAddGrab requires exclusive grab if spring_loaded is TRUE", - (String *) NULL, (Cardinal *) NULL); - exclusive = TRUE; - } - - gl = NewGrabRec(widget, exclusive, spring_loaded); - gl->next = *grabListPtr; - *grabListPtr = gl; - - XtAddCallback (widget, XtNdestroyCallback, - GrabDestroyCallback, (XtPointer) NULL); - UNLOCK_PROCESS; - UNLOCK_APP(app); -} - -void XtRemoveGrab( - Widget widget) -{ - register XtGrabList gl; - register Boolean done; - XtGrabList *grabListPtr; - XtAppContext app = XtWidgetToApplicationContext(widget); - - LOCK_APP(app); - LOCK_PROCESS; - - grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget))); - - for (gl = *grabListPtr; gl != NULL; gl = gl->next) { - if (gl->widget == widget) break; - } - - if (gl == NULL) { - XtAppWarningMsg(app, - "grabError","xtRemoveGrab",XtCXtToolkitError, - "XtRemoveGrab asked to remove a widget not on the list", - (String *)NULL, (Cardinal *)NULL); - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; - } - - do { - gl = *grabListPtr; - done = (gl->widget == widget); - *grabListPtr = gl->next; - XtRemoveCallback(gl->widget, XtNdestroyCallback, - GrabDestroyCallback, (XtPointer)NULL); - XtFree((char *)gl); - } while (! done); - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; -} - -void XtMainLoop(void) -{ - XtAppMainLoop(_XtDefaultAppContext()); -} - -void XtAppMainLoop( - XtAppContext app) -{ - XEvent event; - - LOCK_APP(app); - do { - XtAppNextEvent(app, &event); -#ifdef XTHREADS - /* assert(app == XtDisplayToApplicationContext(event.xany.display)); */ -#endif - XtDispatchEvent(&event); - } while(app->exit_flag == FALSE); - UNLOCK_APP(app); -} - -void _XtFreeEventTable( - XtEventTable *event_table) -{ - register XtEventTable event; - - event = *event_table; - while (event != NULL) { - register XtEventTable next = event->next; - XtFree((char *) event); - event = next; - } -} - -Time XtLastTimestampProcessed( - Display *dpy) -{ - Time time; - DPY_TO_APPCON(dpy); - - LOCK_APP(app); - LOCK_PROCESS; - time = _XtGetPerDisplay(dpy)->last_timestamp; - UNLOCK_PROCESS; - UNLOCK_APP(app); - return(time); -} - -XEvent* XtLastEventProcessed( - Display* dpy) -{ - XEvent* le = NULL; - DPY_TO_APPCON(dpy); - - LOCK_APP(app); - le = &_XtGetPerDisplay(dpy)->last_event; - if (!le->xany.serial) - le = NULL; - UNLOCK_APP(app); - return le; -} - -void _XtSendFocusEvent( - Widget child, - int type) -{ - child = XtIsWidget(child) ? child : _XtWindowedAncestor(child); - if (XtIsSensitive(child) && !child->core.being_destroyed - && XtIsRealized(child) - && (XtBuildEventMask(child) & FocusChangeMask)) - { - XFocusChangeEvent event; - Display* dpy = XtDisplay (child); - - event.type = type; - event.serial = LastKnownRequestProcessed(dpy); - event.send_event = True; - event.display = dpy; - event.window = XtWindow(child); - event.mode = NotifyNormal; - event.detail = NotifyAncestor; - if (XFilterEvent((XEvent*)&event, XtWindow(child))) - return; - XtDispatchEventToWidget(child, (XEvent*)&event); - } -} - -static XtEventDispatchProc* NewDispatcherList(void) -{ - XtEventDispatchProc* l = - (XtEventDispatchProc*) __XtCalloc((Cardinal) 128, - (Cardinal)sizeof(XtEventDispatchProc)); - return l; -} - -XtEventDispatchProc XtSetEventDispatcher( - Display *dpy, - int event_type, - XtEventDispatchProc proc) -{ - XtEventDispatchProc *list; - XtEventDispatchProc old_proc; - register XtPerDisplay pd; - DPY_TO_APPCON(dpy); - - LOCK_APP(app); - LOCK_PROCESS; - pd = _XtGetPerDisplay(dpy); - - list = pd->dispatcher_list; - if (!list) { - if (proc) list = pd->dispatcher_list = NewDispatcherList(); - else return _XtDefaultDispatcher; - } - old_proc = list[event_type]; - list[event_type] = proc; - if (old_proc == NULL) old_proc = _XtDefaultDispatcher; - UNLOCK_PROCESS; - UNLOCK_APP(app); - return old_proc; -} - -void XtRegisterExtensionSelector( - Display *dpy, - int min_event_type, - int max_event_type, - XtExtensionSelectProc proc, - XtPointer client_data) -{ - ExtSelectRec *e; - XtPerDisplay pd; - int i; - DPY_TO_APPCON(dpy); - - if (dpy == NULL) XtErrorMsg("nullDisplay", - "xtRegisterExtensionSelector", XtCXtToolkitError, - "XtRegisterExtensionSelector requires a non-NULL display", - (String *) NULL, (Cardinal *) NULL); - - LOCK_APP(app); - LOCK_PROCESS; - pd = _XtGetPerDisplay(dpy); - - for (i = 0; i < pd->ext_select_count; i++) { - e = &pd->ext_select_list[i]; - if (e->min == min_event_type && e->max == max_event_type) { - e->proc = proc; - e->client_data = client_data; - return; - } - if ((min_event_type >= e->min && min_event_type <= e->max) || - (max_event_type >= e->min && max_event_type <= e->max)) { - XtErrorMsg("rangeError", "xtRegisterExtensionSelector", - XtCXtToolkitError, - "Attempt to register multiple selectors for one extension event type", - (String *) NULL, (Cardinal *) NULL); - UNLOCK_PROCESS; - UNLOCK_APP(app); - return; - } - } - pd->ext_select_count++; - pd->ext_select_list = - (ExtSelectRec *) XtRealloc((char *) pd->ext_select_list, - pd->ext_select_count * sizeof(ExtSelectRec)); - for (i = pd->ext_select_count - 1; i > 0; i--) { - if (pd->ext_select_list[i-1].min > min_event_type) { - pd->ext_select_list[i] = pd->ext_select_list[i-1]; - } else break; - } - pd->ext_select_list[i].min = min_event_type; - pd->ext_select_list[i].max = max_event_type; - pd->ext_select_list[i].proc = proc; - pd->ext_select_list[i].client_data = client_data; - UNLOCK_PROCESS; - UNLOCK_APP(app); -} - -void _XtExtensionSelect( - Widget widget) -{ - int i; - XtPerDisplay pd; - WIDGET_TO_APPCON(widget); - - LOCK_APP(app); - LOCK_PROCESS; - - pd = _XtGetPerDisplay(XtDisplay(widget)); - - for (i = 0; i < pd->ext_select_count; i++) { - CallExtensionSelector(widget, pd->ext_select_list+i, FALSE); - } - UNLOCK_PROCESS; - UNLOCK_APP(app); -} +/***********************************************************
+Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+
+Copyright 1987, 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "IntrinsicI.h"
+#include "Shell.h"
+#include "StringDefs.h"
+
+typedef struct _XtEventRecExt {
+ int type;
+ XtPointer select_data[1]; /* actual dimension is [mask] */
+} XtEventRecExt;
+
+#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type)
+#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n])
+
+#define NonMaskableMask ((EventMask)0x80000000L)
+
+/*
+ * These are definitions to make the code that handles exposure compresssion
+ * easier to read.
+ *
+ * COMP_EXPOSE - The compression exposure field of "widget"
+ * COMP_EXPOSE_TYPE - The type of compression (lower 4 bits of COMP_EXPOSE.
+ * GRAPHICS_EXPOSE - TRUE if the widget wants graphics expose events
+ * dispatched.
+ * NO_EXPOSE - TRUE if the widget wants No expose events dispatched.
+ */
+
+#define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure)
+#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f)
+#define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \
+ (XtExposeGraphicsExposeMerged & COMP_EXPOSE))
+#define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE)
+
+EventMask XtBuildEventMask(
+ Widget widget)
+{
+ XtEventTable ev;
+ EventMask mask = 0L;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ for (ev = widget->core.event_table; ev != NULL; ev = ev->next)
+ if (ev->select) {
+ if (!ev->has_type_specifier)
+ mask |= ev->mask;
+ else {
+ if (EXT_TYPE(ev) < LASTEvent) {
+ Cardinal i;
+ for (i = 0; i < ev->mask; i++)
+ if (EXT_SELECT_DATA(ev, i))
+ mask |= *(EventMask*)EXT_SELECT_DATA(ev, i);
+ }
+ }
+ }
+ LOCK_PROCESS;
+ if (widget->core.widget_class->core_class.expose != NULL)
+ mask |= ExposureMask;
+ if (widget->core.widget_class->core_class.visible_interest)
+ mask |= VisibilityChangeMask;
+ UNLOCK_PROCESS;
+ if (widget->core.tm.translations)
+ mask |= widget->core.tm.translations->eventMask;
+
+ mask = mask & ~NonMaskableMask;
+ UNLOCK_APP(app);
+ return mask;
+}
+
+static void CallExtensionSelector(
+ Widget widget,
+ ExtSelectRec* rec,
+ Boolean forceCall)
+{
+ XtEventRec* p;
+ XtPointer* data;
+ int* types;
+ Cardinal i, count = 0;
+
+ for (p = widget->core.event_table; p != NULL; p = p->next)
+ if (p->has_type_specifier &&
+ EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
+ count += p->mask;
+
+ if (count == 0 && !forceCall) return;
+
+ data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer));
+ types = (int *) ALLOCATE_LOCAL(count * sizeof (int));
+ count = 0;
+
+ for (p = widget->core.event_table; p != NULL; p = p->next)
+ if (p->has_type_specifier &&
+ EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max)
+ for (i =0; i < p->mask; i++) {
+ types[count] = EXT_TYPE(p);
+ data[count++] = EXT_SELECT_DATA(p, i);
+ }
+
+ (*rec->proc)(widget, types, data, count, rec->client_data);
+ DEALLOCATE_LOCAL((char*) types);
+ DEALLOCATE_LOCAL((char*) data);
+}
+
+static void
+RemoveEventHandler(
+ Widget widget,
+ XtPointer select_data,
+ int type,
+ Boolean has_type_specifier,
+ Boolean other,
+ XtEventHandler proc,
+ XtPointer closure,
+ Boolean raw)
+{
+ XtEventRec *p, **pp;
+ EventMask eventMask, oldMask = XtBuildEventMask(widget);
+
+ if (raw) raw = 1;
+ pp = &widget->core.event_table;
+ while ((p = *pp) &&
+ (p->proc != proc || p->closure != closure || p->select == raw ||
+ has_type_specifier != p->has_type_specifier ||
+ (has_type_specifier && EXT_TYPE(p) != type)))
+ pp = &p->next;
+ if (!p) return;
+
+ /* un-register it */
+ if (!has_type_specifier) {
+ eventMask = *(EventMask*)select_data;
+ eventMask &= ~NonMaskableMask;
+ if (other)
+ eventMask |= NonMaskableMask;
+ p->mask &= ~eventMask;
+ } else {
+ Cardinal i;
+ /* p->mask specifies count of EXT_SELECT_DATA(p,i)
+ * search through the list of selection data, if not found
+ * dont remove this handler
+ */
+ for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++;
+ if (i == p->mask) return;
+ if (p->mask == 1) p->mask = 0;
+ else {
+ p->mask--;
+ while (i < p->mask) {
+ EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1);
+ i++;
+ }
+ }
+ }
+
+ if (!p->mask) { /* delete it entirely */
+ *pp = p->next;
+ XtFree((char *)p);
+ }
+
+ /* Reset select mask if realized and not raw. */
+ if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) {
+ EventMask mask = XtBuildEventMask(widget);
+ Display* dpy = XtDisplay (widget);
+
+ if (oldMask != mask)
+ XSelectInput(dpy, XtWindow(widget), mask);
+
+ if (has_type_specifier) {
+ XtPerDisplay pd = _XtGetPerDisplay(dpy);
+ int i;
+ for (i = 0; i < pd->ext_select_count; i++) {
+ if (type >= pd->ext_select_list[i].min &&
+ type <= pd->ext_select_list[i].max) {
+ CallExtensionSelector(widget, pd->ext_select_list+i, TRUE);
+ break;
+ }
+ if (type < pd->ext_select_list[i].min) break;
+ }
+ }
+ }
+}
+
+/* Function Name: AddEventHandler
+ * Description: An Internal routine that does the actual work of
+ * adding the event handlers.
+ * Arguments: widget - widget to register an event handler for.
+ * eventMask - events to mask for.
+ * other - pass non maskable events to this proceedure.
+ * proc - proceedure to register.
+ * closure - data to pass to the event hander.
+ * position - where to add this event handler.
+ * force_new_position - If the element is already in the
+ * list, this will force it to the
+ * beginning or end depending on position.
+ * raw - If FALSE call XSelectInput for events in mask.
+ * Returns: none
+ */
+
+static void
+AddEventHandler(
+ Widget widget,
+ XtPointer select_data,
+ int type,
+ Boolean has_type_specifier,
+ Boolean other,
+ XtEventHandler proc,
+ XtPointer closure,
+ XtListPosition position,
+ Boolean force_new_position,
+ Boolean raw)
+{
+ register XtEventRec *p, **pp;
+ EventMask oldMask = 0, eventMask = 0;
+
+ if (!has_type_specifier) {
+ eventMask = *(EventMask*)select_data & ~NonMaskableMask;
+ if (other) eventMask |= NonMaskableMask;
+ if (!eventMask) return;
+ } else if (!type) return;
+
+ if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget);
+
+ if (raw) raw = 1;
+ pp = &widget->core.event_table;
+ while ((p = *pp) &&
+ (p->proc != proc || p->closure != closure || p->select == raw ||
+ has_type_specifier != p->has_type_specifier ||
+ (has_type_specifier && EXT_TYPE(p) != type)))
+ pp = &p->next;
+
+ if (!p) { /* New proc to add to list */
+ if (has_type_specifier) {
+ p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) +
+ sizeof(XtEventRecExt));
+ EXT_TYPE(p) = type;
+ EXT_SELECT_DATA(p,0) = select_data;
+ p->mask = 1;
+ p->has_type_specifier = True;
+ } else {
+ p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec));
+ p->mask = eventMask;
+ p->has_type_specifier = False;
+ }
+ p->proc = proc;
+ p->closure = closure;
+ p->select = ! raw;
+
+ if (position == XtListHead) {
+ p->next = widget->core.event_table;
+ widget->core.event_table = p;
+ pp = &widget->core.event_table;
+ } else {
+ *pp = p;
+ p->next = NULL;
+ }
+ }
+ else {
+ if (force_new_position) {
+ *pp = p->next;
+
+ if (position == XtListHead) {
+ p->next = widget->core.event_table;
+ widget->core.event_table = p;
+ } else {
+ /*
+ * Find the last element in the list.
+ */
+ while (*pp)
+ pp = &(*pp)->next;
+ *pp = p;
+ p->next = NULL;
+ }
+ }
+
+ if (!has_type_specifier)
+ p->mask |= eventMask;
+ else {
+ Cardinal i;
+ /* p->mask specifies count of EXT_SELECT_DATA(p,i) */
+ for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); )
+ i++;
+ if (i == p->mask) {
+ p = (XtEventRec*) XtRealloc((char*)p,
+ sizeof(XtEventRec) +
+ sizeof(XtEventRecExt) +
+ p->mask * sizeof(XtPointer));
+ EXT_SELECT_DATA(p,i) = select_data;
+ p->mask++;
+ *pp = p;
+ }
+ }
+ }
+
+ if (XtIsRealized(widget) && !raw) {
+ EventMask mask = XtBuildEventMask(widget);
+ Display* dpy = XtDisplay (widget);
+
+ if (oldMask != mask)
+ XSelectInput(dpy, XtWindow(widget), mask);
+
+ if (has_type_specifier) {
+ XtPerDisplay pd = _XtGetPerDisplay (dpy);
+ int i;
+ for (i = 0; i < pd->ext_select_count; i++) {
+ if (type >= pd->ext_select_list[i].min &&
+ type <= pd->ext_select_list[i].max) {
+ CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
+ break;
+ }
+ if (type < pd->ext_select_list[i].min) break;
+ }
+ }
+ }
+}
+
+void XtRemoveEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
+ other, proc, closure, FALSE);
+ UNLOCK_APP(app);
+}
+
+void XtAddEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
+ proc, closure, XtListTail, FALSE, FALSE);
+ UNLOCK_APP(app);
+}
+
+void XtInsertEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure,
+ XtListPosition position)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
+ proc, closure, position, TRUE, FALSE);
+ UNLOCK_APP(app);
+}
+
+void XtRemoveRawEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE,
+ other, proc, closure, TRUE);
+ UNLOCK_APP(app);
+}
+
+void XtInsertRawEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure,
+ XtListPosition position)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
+ proc, closure, position, TRUE, TRUE);
+ UNLOCK_APP(app);
+}
+
+void XtAddRawEventHandler(
+ Widget widget,
+ EventMask eventMask,
+ _XtBoolean other,
+ XtEventHandler proc,
+ XtPointer closure)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other,
+ proc, closure, XtListTail, FALSE, TRUE);
+ UNLOCK_APP(app);
+}
+
+void XtRemoveEventTypeHandler(
+ Widget widget,
+ int type,
+ XtPointer select_data,
+ XtEventHandler proc,
+ XtPointer closure)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ RemoveEventHandler(widget, select_data, type, TRUE,
+ FALSE, proc, closure, FALSE);
+ UNLOCK_APP(app);
+}
+
+void XtInsertEventTypeHandler(
+ Widget widget,
+ int type,
+ XtPointer select_data,
+ XtEventHandler proc,
+ XtPointer closure,
+ XtListPosition position)
+{
+ WIDGET_TO_APPCON(widget);
+ LOCK_APP(app);
+ AddEventHandler(widget, select_data, type, TRUE, FALSE,
+ proc, closure, position, TRUE, FALSE);
+ UNLOCK_APP(app);
+}
+
+typedef struct _WWPair {
+ struct _WWPair *next;
+ Window window;
+ Widget widget;
+} *WWPair;
+
+typedef struct _WWTable {
+ unsigned int mask; /* size of hash table - 1 */
+ unsigned int rehash; /* mask - 2 */
+ unsigned int occupied; /* number of occupied entries */
+ unsigned int fakes; /* number occupied by WWfake */
+ Widget *entries; /* the entries */
+ WWPair pairs; /* bogus entries */
+} *WWTable;
+
+static const WidgetRec WWfake; /* placeholder for deletions */
+
+#define WWHASH(tab,win) ((win) & tab->mask)
+#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1)
+#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask)
+#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable)
+
+static void ExpandWWTable(WWTable);
+
+void XtRegisterDrawable(
+ Display* display,
+ Drawable drawable,
+ Widget widget)
+{
+ WWTable tab;
+ int idx, rehash;
+ Widget entry;
+ Window window = (Window) drawable;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ tab = WWTABLE(display);
+ if (window != XtWindow(widget)) {
+ WWPair pair;
+ pair = XtNew(struct _WWPair);
+ pair->next = tab->pairs;
+ pair->window = window;
+ pair->widget = widget;
+ tab->pairs = pair;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+ }
+ if ((tab->occupied + (tab->occupied >> 2)) > tab->mask)
+ ExpandWWTable(tab);
+
+ idx = WWHASH(tab, window);
+ if ((entry = tab->entries[idx]) && entry != &WWfake) {
+ rehash = WWREHASHVAL(tab, window);
+ do {
+ idx = WWREHASH(tab, idx, rehash);
+ } while ((entry = tab->entries[idx]) && entry != &WWfake);
+ }
+ if (!entry)
+ tab->occupied++;
+ else if (entry == &WWfake)
+ tab->fakes--;
+ tab->entries[idx] = widget;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+}
+
+void XtUnregisterDrawable(
+ Display* display,
+ Drawable drawable)
+{
+ WWTable tab;
+ int idx, rehash;
+ Widget entry;
+ Window window = (Window) drawable;
+ Widget widget = XtWindowToWidget (display, window);
+ DPY_TO_APPCON(display);
+
+ if (widget == NULL) return;
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ tab = WWTABLE(display);
+ if (window != XtWindow(widget)) {
+ WWPair *prev, pair;
+
+ prev = &tab->pairs;
+ while ((pair = *prev) && pair->window != window)
+ prev = &pair->next;
+ if (pair) {
+ *prev = pair->next;
+ XtFree((char *)pair);
+ }
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+ }
+ idx = WWHASH(tab, window);
+ if ((entry = tab->entries[idx])) {
+ if (entry != widget) {
+ rehash = WWREHASHVAL(tab, window);
+ do {
+ idx = WWREHASH(tab, idx, rehash);
+ if (!(entry = tab->entries[idx])) {
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+ }
+ } while (entry != widget);
+ }
+ tab->entries[idx] = (Widget)&WWfake;
+ tab->fakes++;
+ }
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+}
+
+static void ExpandWWTable(
+ register WWTable tab)
+{
+ unsigned int oldmask;
+ register Widget *oldentries, *entries;
+ register Cardinal oldidx, newidx, rehash;
+ register Widget entry;
+
+ LOCK_PROCESS;
+ oldmask = tab->mask;
+ oldentries = tab->entries;
+ tab->occupied -= tab->fakes;
+ tab->fakes = 0;
+ if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) {
+ tab->mask = (tab->mask << 1) + 1;
+ tab->rehash = tab->mask - 2;
+ }
+ entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
+ for (oldidx = 0; oldidx <= oldmask; oldidx++) {
+ if ((entry = oldentries[oldidx]) && entry != &WWfake) {
+ newidx = WWHASH(tab, XtWindow(entry));
+ if (entries[newidx]) {
+ rehash = WWREHASHVAL(tab, XtWindow(entry));
+ do {
+ newidx = WWREHASH(tab, newidx, rehash);
+ } while (entries[newidx]);
+ }
+ entries[newidx] = entry;
+ }
+ }
+ XtFree((char *)oldentries);
+ UNLOCK_PROCESS;
+}
+
+Widget XtWindowToWidget(
+ register Display *display,
+ register Window window)
+{
+ register WWTable tab;
+ register int idx, rehash;
+ register Widget entry;
+ WWPair pair;
+ DPY_TO_APPCON(display);
+
+ if (!window) return NULL;
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ tab = WWTABLE(display);
+ idx = WWHASH(tab, window);
+ if ((entry = tab->entries[idx]) && XtWindow(entry) != window) {
+ rehash = WWREHASHVAL(tab, window);
+ do {
+ idx = WWREHASH(tab, idx, rehash);
+ } while ((entry = tab->entries[idx]) && XtWindow(entry) != window);
+ }
+ if (entry) {
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return entry;
+ }
+ for (pair = tab->pairs; pair; pair = pair->next) {
+ if (pair->window == window) {
+ entry = pair->widget;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return entry;
+ }
+ }
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return NULL;
+}
+
+void _XtAllocWWTable(
+ XtPerDisplay pd)
+{
+ register WWTable tab;
+
+ tab = (WWTable) __XtMalloc(sizeof(struct _WWTable));
+ tab->mask = 0x7f;
+ tab->rehash = tab->mask - 2;
+ tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget));
+ tab->occupied = 0;
+ tab->fakes = 0;
+ tab->pairs = NULL;
+ pd->WWtable = tab;
+}
+
+void _XtFreeWWTable(
+ register XtPerDisplay pd)
+{
+ register WWPair pair, next;
+
+ for (pair = pd->WWtable->pairs; pair; pair = next) {
+ next = pair->next;
+ XtFree((char *)pair);
+ }
+ XtFree((char *)pd->WWtable->entries);
+ XtFree((char *)pd->WWtable);
+}
+
+#define EHMAXSIZE 25 /* do not make whopping big */
+
+static Boolean CallEventHandlers(
+ Widget widget,
+ XEvent *event,
+ EventMask mask)
+{
+ register XtEventRec *p;
+ XtEventHandler *proc;
+ XtPointer *closure;
+ XtEventHandler procs[EHMAXSIZE];
+ XtPointer closures[EHMAXSIZE];
+ Boolean cont_to_disp = True;
+ int i, numprocs;
+
+ /* Have to copy the procs into an array, because one of them might
+ * call XtRemoveEventHandler, which would break our linked list. */
+
+ numprocs = 0;
+ for (p=widget->core.event_table; p; p = p->next) {
+ if ((!p->has_type_specifier && (mask & p->mask)) ||
+ (p->has_type_specifier && event->type == EXT_TYPE(p)))
+ numprocs++;
+ }
+ if (numprocs > EHMAXSIZE) {
+ proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) +
+ sizeof(XtPointer)));
+ closure = (XtPointer *)(proc + numprocs);
+ } else {
+ proc = procs;
+ closure = closures;
+ }
+ numprocs = 0;
+ for (p=widget->core.event_table; p; p = p->next) {
+ if ((!p->has_type_specifier && (mask & p->mask)) ||
+ (p->has_type_specifier && event->type == EXT_TYPE(p))) {
+ proc[numprocs] = p->proc;
+ closure[numprocs] = p->closure;
+ numprocs++;
+ }
+ }
+/* FUNCTIONS CALLED THROUGH POINTER proc:
+ Selection.c:ReqCleanup,
+ "Shell.c":EventHandler,
+ PassivGrab.c:ActiveHandler,
+ PassivGrab.c:RealizeHandler,
+ Keyboard.c:QueryEventMask,
+ _XtHandleFocus,
+ Selection.c:HandleSelectionReplies,
+ Selection.c:HandleGetIncrement,
+ Selection.c:HandleIncremental,
+ Selection.c:HandlePropertyGone,
+ Selection.c:HandleSelectionEvents
+ */
+ for (i = 0; i < numprocs && cont_to_disp; i++)
+ (*(proc[i]))(widget, closure[i], event, &cont_to_disp);
+ if (numprocs > EHMAXSIZE)
+ XtFree((char *)proc);
+ return cont_to_disp;
+}
+
+static void CompressExposures(XEvent *, Widget);
+
+#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\
+ Button4MotionMask|Button5MotionMask)
+
+/* keep this SMALL to avoid blowing stack cache! */
+/* because some compilers allocate all local locals on procedure entry */
+#define EHSIZE 4
+
+Boolean XtDispatchEventToWidget(
+ Widget widget,
+ XEvent* event)
+{
+ register XtEventRec *p;
+ Boolean was_dispatched = False;
+ Boolean call_tm = False;
+ Boolean cont_to_disp;
+ EventMask mask;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+
+ mask = _XtConvertTypeToMask(event->type);
+ if (event->type == MotionNotify)
+ mask |= (event->xmotion.state & KnownButtons);
+
+ LOCK_PROCESS;
+ if ( (mask == ExposureMask) ||
+ ((event->type == NoExpose) && NO_EXPOSE) ||
+ ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) {
+
+ if (widget->core.widget_class->core_class.expose != NULL ) {
+
+ /* We need to mask off the bits that could contain the information
+ * about whether or not we desire Graphics and NoExpose events. */
+
+ if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) ||
+ (event->type == NoExpose) )
+
+ (*widget->core.widget_class->core_class.expose)
+ (widget, event, (Region)NULL);
+ else {
+ CompressExposures(event, widget);
+ }
+ was_dispatched = True;
+ }
+ }
+
+ if ((mask == VisibilityChangeMask) &&
+ XtClass(widget)->core_class.visible_interest) {
+ was_dispatched = True;
+ /* our visibility just changed... */
+ switch (((XVisibilityEvent *)event)->state) {
+ case VisibilityUnobscured:
+ widget->core.visible = TRUE;
+ break;
+
+ case VisibilityPartiallyObscured:
+ /* what do we want to say here? */
+ /* well... some of us is visible */
+ widget->core.visible = TRUE;
+ break;
+
+ case VisibilityFullyObscured:
+ widget->core.visible = FALSE;
+ /* do we want to mark our children obscured? */
+ break;
+ }
+ }
+ UNLOCK_PROCESS;
+
+ /* to maintain "copy" semantics we check TM now but call later */
+ if (widget->core.tm.translations &&
+ (mask & widget->core.tm.translations->eventMask))
+ call_tm = True;
+
+ cont_to_disp = True;
+ p=widget->core.event_table;
+ if (p) {
+ if (p->next) {
+ XtEventHandler proc[EHSIZE];
+ XtPointer closure[EHSIZE];
+ int numprocs = 0;
+
+ /* Have to copy the procs into an array, because one of them might
+ * call XtRemoveEventHandler, which would break our linked list. */
+
+ for (; p; p = p->next) {
+ if ((!p->has_type_specifier && (mask & p->mask)) ||
+ (p->has_type_specifier && event->type == EXT_TYPE(p))) {
+ if (numprocs >= EHSIZE)
+ break;
+ proc[numprocs] = p->proc;
+ closure[numprocs] = p->closure;
+ numprocs++;
+ }
+ }
+ if (numprocs) {
+ if (p) {
+ cont_to_disp = CallEventHandlers(widget, event, mask);
+ } else {
+ int i;
+ for (i = 0; i < numprocs && cont_to_disp; i++)
+ (*(proc[i]))(widget, closure[i], event, &cont_to_disp);
+/* FUNCTIONS CALLED THROUGH POINTER proc:
+ Selection.c:ReqCleanup,
+ "Shell.c":EventHandler,
+ PassivGrab.c:ActiveHandler,
+ PassivGrab.c:RealizeHandler,
+ Keyboard.c:QueryEventMask,
+ _XtHandleFocus,
+ Selection.c:HandleSelectionReplies,
+ Selection.c:HandleGetIncrement,
+ Selection.c:HandleIncremental,
+ Selection.c:HandlePropertyGone,
+ Selection.c:HandleSelectionEvents
+ */
+ }
+ was_dispatched = True;
+ }
+ } else if ((!p->has_type_specifier && (mask & p->mask)) ||
+ (p->has_type_specifier && event->type == EXT_TYPE(p))) {
+ (*p->proc)(widget, p->closure, event, &cont_to_disp);
+ was_dispatched = True;
+ }
+ }
+ if (call_tm && cont_to_disp)
+ _XtTranslateEvent(widget, event);
+ UNLOCK_APP(app);
+ return (was_dispatched|call_tm);
+}
+
+/*
+ * This structure is passed into the check exposure proc.
+ */
+
+typedef struct _CheckExposeInfo {
+ int type1, type2; /* Types of events to check for. */
+ Boolean maximal; /* Ignore non-exposure events? */
+ Boolean non_matching; /* Was there an event that did not
+ match either type? */
+ Window window; /* Window to match. */
+} CheckExposeInfo;
+
+#define GetCount(ev) (((XExposeEvent *)(ev))->count)
+
+static void SendExposureEvent(XEvent *, Widget, XtPerDisplay);
+static Bool CheckExposureEvent(Display *, XEvent *, char *);
+static void AddExposureToRectangularRegion(XEvent *, Region);
+
+/* Function Name: CompressExposures
+ * Description: Handles all exposure compression
+ * Arguments: event - the xevent that is to be dispatched
+ * widget - the widget that this event occured in.
+ * Returns: none.
+ *
+ * NOTE: Event must be of type Expose or GraphicsExpose.
+ */
+
+static void
+CompressExposures(
+XEvent * event,
+Widget widget)
+{
+ CheckExposeInfo info;
+ int count;
+ Display* dpy = XtDisplay (widget);
+ XtPerDisplay pd = _XtGetPerDisplay(dpy);
+ XtEnum comp_expose;
+ XtEnum comp_expose_type;
+ Boolean no_region;
+
+ LOCK_PROCESS;
+ comp_expose = COMP_EXPOSE;
+ UNLOCK_PROCESS;
+ comp_expose_type = comp_expose & 0x0f;
+ no_region = ((comp_expose & XtExposeNoRegion) ? True : False);
+
+ if (no_region)
+ AddExposureToRectangularRegion(event, pd->region);
+ else
+ XtAddExposureToRegion(event, pd->region);
+
+ if ( GetCount(event) != 0 )
+ return;
+
+ if ((comp_expose_type == XtExposeCompressSeries) ||
+ (XEventsQueued(dpy, QueuedAfterReading) == 0)) {
+ SendExposureEvent(event, widget, pd);
+ return;
+ }
+
+ if (comp_expose & XtExposeGraphicsExposeMerged) {
+ info.type1 = Expose;
+ info.type2 = GraphicsExpose;
+ }
+ else {
+ info.type1 = event->type;
+ info.type2 = 0;
+ }
+ info.maximal = (comp_expose_type == XtExposeCompressMaximal);
+ info.non_matching = FALSE;
+ info.window = XtWindow(widget);
+
+/*
+ * We have to be very careful here not to hose down the processor
+ * when blocking until count gets to zero.
+ *
+ * First, check to see if there are any events in the queue for this
+ * widget, and of the correct type.
+ *
+ * Once we cannot find any more events, check to see that count is zero.
+ * If it is not then block until we get another exposure event.
+ *
+ * If we find no more events, and count on the last one we saw was zero we
+ * we can be sure that all events have been processed.
+ *
+ * Unfortunately, we wind up having to look at the entire queue
+ * event if we're not doing Maximal compression, due to the
+ * semantics of XCheckIfEvent (we can't abort without re-ordering
+ * the event queue as a side-effect).
+ */
+
+ count = 0;
+ while (TRUE) {
+ XEvent event_return;
+
+ if (XCheckIfEvent(dpy, &event_return,
+ CheckExposureEvent, (char *) &info)) {
+
+ count = GetCount(&event_return);
+ if (no_region)
+ AddExposureToRectangularRegion(&event_return, pd->region);
+ else
+ XtAddExposureToRegion(&event_return, pd->region);
+ }
+ else if (count != 0) {
+ XIfEvent(dpy, &event_return,
+ CheckExposureEvent, (char *) &info);
+ count = GetCount(&event_return);
+ if (no_region)
+ AddExposureToRectangularRegion(&event_return, pd->region);
+ else
+ XtAddExposureToRegion(&event_return, pd->region);
+ }
+ else /* count == 0 && XCheckIfEvent Failed. */
+ break;
+ }
+
+ SendExposureEvent(event, widget, pd);
+}
+
+void XtAddExposureToRegion(
+ XEvent *event,
+ Region region)
+{
+ XRectangle rect;
+ XExposeEvent *ev = (XExposeEvent *) event;
+ /* These Expose and GraphicsExpose fields are at identical offsets */
+
+ if (event->type == Expose || event->type == GraphicsExpose) {
+ rect.x = ev->x;
+ rect.y = ev->y;
+ rect.width = ev->width;
+ rect.height = ev->height;
+ XUnionRectWithRegion(&rect, region, region);
+ }
+}
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+static void AddExposureToRectangularRegion(
+ XEvent *event, /* when called internally, type is always appropriate */
+ Region region)
+{
+ XRectangle rect;
+ XExposeEvent *ev = (XExposeEvent *) event;
+ /* These Expose and GraphicsExpose fields are at identical offsets */
+
+ rect.x = ev->x;
+ rect.y = ev->y;
+ rect.width = ev->width;
+ rect.height = ev->height;
+
+ if (XEmptyRegion(region)) {
+ XUnionRectWithRegion(&rect, region, region);
+ } else {
+ XRectangle merged, bbox;
+
+ XClipBox(region, &bbox);
+ merged.x = MIN(rect.x, bbox.x);
+ merged.y = MIN(rect.y, bbox.y);
+ merged.width = MAX(rect.x + rect.width,
+ bbox.x + bbox.width) - merged.x;
+ merged.height = MAX(rect.y + rect.height,
+ bbox.y + bbox.height) - merged.y;
+ XUnionRectWithRegion(&merged, region, region);
+ }
+}
+
+static Region nullRegion;
+/* READ-ONLY VARIABLES: nullRegion */
+
+void _XtEventInitialize(void)
+{
+#ifndef __lock_lint
+ nullRegion = XCreateRegion();
+#endif
+}
+
+/* Function Name: SendExposureEvent
+ * Description: Sets the x, y, width, and height of the event
+ * to be the clip box of Expose Region.
+ * Arguments: event - the X Event to mangle; Expose or GraphicsExpose.
+ * widget - the widget that this event occured in.
+ * pd - the per display information for this widget.
+ * Returns: none.
+ */
+
+static void
+SendExposureEvent(
+XEvent * event,
+Widget widget,
+XtPerDisplay pd)
+{
+ XtExposeProc expose;
+ XRectangle rect;
+ XtEnum comp_expose;
+ XExposeEvent *ev = (XExposeEvent *) event;
+
+ XClipBox(pd->region, &rect);
+ ev->x = rect.x;
+ ev->y = rect.y;
+ ev->width = rect.width;
+ ev->height = rect.height;
+
+ LOCK_PROCESS;
+ comp_expose = COMP_EXPOSE;
+ expose = widget->core.widget_class->core_class.expose;
+ UNLOCK_PROCESS;
+ if (comp_expose & XtExposeNoRegion)
+ (*expose)(widget, event, NULL);
+ else
+ (*expose)(widget, event, pd->region);
+ (void) XIntersectRegion(nullRegion, pd->region, pd->region);
+}
+
+/* Function Name: CheckExposureEvent
+ * Description: Checks the event queue for an expose event
+ * Arguments: display - the display connection.
+ * event - the event to check.
+ * arg - a pointer to the exposure info structure.
+ * Returns: TRUE if we found an event of the correct type
+ * with the right window.
+ *
+ * NOTE: The only valid types (info.type1 and info.type2) are Expose
+ * and GraphicsExpose.
+ */
+
+/* ARGSUSED */
+static Bool
+CheckExposureEvent(
+Display * disp,
+XEvent * event,
+char * arg)
+{
+ CheckExposeInfo * info = ((CheckExposeInfo *) arg);
+
+ if ( (info->type1 == event->type) || (info->type2 == event->type)) {
+ if (!info->maximal && info->non_matching) return FALSE;
+ if (event->type == GraphicsExpose)
+ return(event->xgraphicsexpose.drawable == info->window);
+ return(event->xexpose.window == info->window);
+ }
+ info->non_matching = TRUE;
+ return(FALSE);
+}
+
+static EventMask const masks[] = {
+ 0, /* Error, should never see */
+ 0, /* Reply, should never see */
+ KeyPressMask, /* KeyPress */
+ KeyReleaseMask, /* KeyRelease */
+ ButtonPressMask, /* ButtonPress */
+ ButtonReleaseMask, /* ButtonRelease */
+ PointerMotionMask /* MotionNotify */
+ | ButtonMotionMask,
+ EnterWindowMask, /* EnterNotify */
+ LeaveWindowMask, /* LeaveNotify */
+ FocusChangeMask, /* FocusIn */
+ FocusChangeMask, /* FocusOut */
+ KeymapStateMask, /* KeymapNotify */
+ ExposureMask, /* Expose */
+ NonMaskableMask, /* GraphicsExpose, in GC */
+ NonMaskableMask, /* NoExpose, in GC */
+ VisibilityChangeMask, /* VisibilityNotify */
+ SubstructureNotifyMask, /* CreateNotify */
+ StructureNotifyMask /* DestroyNotify */
+ | SubstructureNotifyMask,
+ StructureNotifyMask /* UnmapNotify */
+ | SubstructureNotifyMask,
+ StructureNotifyMask /* MapNotify */
+ | SubstructureNotifyMask,
+ SubstructureRedirectMask, /* MapRequest */
+ StructureNotifyMask /* ReparentNotify */
+ | SubstructureNotifyMask,
+ StructureNotifyMask /* ConfigureNotify */
+ | SubstructureNotifyMask,
+ SubstructureRedirectMask, /* ConfigureRequest */
+ StructureNotifyMask /* GravityNotify */
+ | SubstructureNotifyMask,
+ ResizeRedirectMask, /* ResizeRequest */
+ StructureNotifyMask /* CirculateNotify */
+ | SubstructureNotifyMask,
+ SubstructureRedirectMask, /* CirculateRequest */
+ PropertyChangeMask, /* PropertyNotify */
+ NonMaskableMask, /* SelectionClear */
+ NonMaskableMask, /* SelectionRequest */
+ NonMaskableMask, /* SelectionNotify */
+ ColormapChangeMask, /* ColormapNotify */
+ NonMaskableMask, /* ClientMessage */
+ NonMaskableMask /* MappingNotify */
+};
+
+EventMask _XtConvertTypeToMask (
+ int eventType)
+{
+ if ((Cardinal) eventType < XtNumber(masks))
+ return masks[eventType];
+ else
+ return NoEventMask;
+}
+
+Boolean _XtOnGrabList(
+ register Widget widget,
+ XtGrabRec *grabList)
+{
+ register XtGrabRec* gl;
+ for (; widget != NULL; widget = (Widget)widget->core.parent) {
+ for (gl = grabList; gl != NULL; gl = gl->next) {
+ if (gl->widget == widget) return TRUE;
+ if (gl->exclusive) break;
+ }
+ }
+ return FALSE;
+}
+
+static Widget LookupSpringLoaded(
+ XtGrabList grabList)
+{
+ XtGrabList gl;
+
+ for (gl = grabList; gl != NULL; gl = gl->next) {
+ if (gl->spring_loaded) {
+ if (XtIsSensitive(gl->widget))
+ return gl->widget;
+ else
+ return NULL;
+ }
+ if (gl->exclusive) break;
+ }
+ return NULL;
+}
+
+static Boolean DispatchEvent(
+ XEvent* event,
+ Widget widget)
+{
+
+ if (event->type == EnterNotify &&
+ event->xcrossing.mode == NotifyNormal &&
+ widget->core.widget_class->core_class.compress_enterleave) {
+ if (XPending(event->xcrossing.display)) {
+ XEvent nextEvent;
+ XPeekEvent(event->xcrossing.display, &nextEvent);
+ if (nextEvent.type == LeaveNotify &&
+ event->xcrossing.window == nextEvent.xcrossing.window &&
+ nextEvent.xcrossing.mode == NotifyNormal &&
+ ((event->xcrossing.detail != NotifyInferior &&
+ nextEvent.xcrossing.detail != NotifyInferior) ||
+ (event->xcrossing.detail == NotifyInferior &&
+ nextEvent.xcrossing.detail == NotifyInferior))) {
+ /* skip the enter/leave pair */
+ XNextEvent(event->xcrossing.display, &nextEvent);
+ return False;
+ }
+ }
+ }
+
+ if (event->type == MotionNotify &&
+ widget->core.widget_class->core_class.compress_motion) {
+ while (XPending(event->xmotion.display)) {
+ XEvent nextEvent;
+ XPeekEvent(event->xmotion.display, &nextEvent);
+ if (nextEvent.type == MotionNotify &&
+ event->xmotion.window == nextEvent.xmotion.window &&
+ event->xmotion.subwindow == nextEvent.xmotion.subwindow) {
+ /* replace the current event with the next one */
+ XNextEvent(event->xmotion.display, event);
+ } else break;
+ }
+ }
+
+ return XtDispatchEventToWidget(widget, event);
+}
+
+typedef enum _GrabType {pass, ignore, remap} GrabType;
+
+#if !defined(AIXV3) || !defined(AIXSHLIB)
+static /* AIX shared libraries are broken */
+#endif
+Boolean _XtDefaultDispatcher(
+ XEvent *event)
+{
+ register Widget widget;
+ GrabType grabType;
+ XtPerDisplayInput pdi;
+ XtGrabList grabList;
+ Boolean was_dispatched = False;
+ DPY_TO_APPCON(event->xany.display);
+
+ /* the default dispatcher discards all extension events */
+ if (event->type >= LASTEvent)
+ return False;
+
+ LOCK_APP(app);
+
+ switch (event->type) {
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease: grabType = remap; break;
+ case MotionNotify:
+ case EnterNotify: grabType = ignore; break;
+ default: grabType = pass; break;
+ }
+
+ widget = XtWindowToWidget (event->xany.display, event->xany.window);
+ pdi = _XtGetPerDisplayInput(event->xany.display);
+ grabList = *_XtGetGrabList(pdi);
+
+ if (widget == NULL) {
+ if (grabType == remap
+ && (widget = LookupSpringLoaded(grabList)) != NULL) {
+ /* event occurred in a non-widget window, but we've promised also
+ to dispatch it to the nearest accessible spring_loaded widget */
+ was_dispatched = (XFilterEvent(event, XtWindow(widget))
+ || XtDispatchEventToWidget(widget, event));
+ }
+ else was_dispatched = XFilterEvent(event, None);
+ }
+ else if (grabType == pass) {
+ if (event->type == LeaveNotify ||
+ event->type == FocusIn ||
+ event->type == FocusOut) {
+ if (XtIsSensitive (widget))
+ was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
+ XtDispatchEventToWidget(widget, event));
+ } else was_dispatched = (XFilterEvent(event, XtWindow(widget)) ||
+ XtDispatchEventToWidget(widget, event));
+ }
+ else if (grabType == ignore) {
+ if ((grabList == NULL || _XtOnGrabList(widget, grabList))
+ && XtIsSensitive(widget)) {
+ was_dispatched = (XFilterEvent(event, XtWindow(widget))
+ || DispatchEvent(event, widget));
+ }
+ }
+ else if (grabType == remap) {
+ EventMask mask = _XtConvertTypeToMask(event->type);
+ Widget dspWidget;
+ Boolean was_filtered = False;
+
+ dspWidget = _XtFindRemapWidget(event, widget, mask, pdi);
+
+ if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList))
+ && XtIsSensitive(dspWidget)) {
+ if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) {
+ /* If this event activated a device grab, release it. */
+ _XtUngrabBadGrabs(event, widget, mask, pdi);
+ was_dispatched = True;
+ } else
+ was_dispatched = XtDispatchEventToWidget(dspWidget, event);
+ }
+ else _XtUngrabBadGrabs(event, widget, mask, pdi);
+
+ if (!was_filtered) {
+ /* 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 = (XFilterEvent(event, XtWindow(widget))
+ || XtDispatchEventToWidget(widget, event)
+ || was_dispatched);
+ }
+ }
+ }
+ UNLOCK_APP(app);
+ return was_dispatched;
+}
+
+Boolean XtDispatchEvent (
+ XEvent *event)
+{
+ Boolean was_dispatched, safe;
+ int dispatch_level;
+ int starting_count;
+ XtPerDisplay pd;
+ Time time = 0;
+ XtEventDispatchProc dispatch = _XtDefaultDispatcher;
+ XtAppContext app = XtDisplayToApplicationContext(event->xany.display);
+
+ LOCK_APP(app);
+ dispatch_level = ++app->dispatch_level;
+ starting_count = app->destroy_count;
+
+ switch (event->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;
+
+ case MappingNotify: _XtRefreshMapping(event, True); break;
+ }
+ pd = _XtGetPerDisplay(event->xany.display);
+ if (time) pd->last_timestamp = time;
+ pd->last_event = *event;
+
+ if (pd->dispatcher_list) {
+ dispatch = pd->dispatcher_list[event->type];
+ if (dispatch == NULL) dispatch = _XtDefaultDispatcher;
+ }
+ was_dispatched = (*dispatch)(event);
+
+ /*
+ * To make recursive XtDispatchEvent work, we need to do phase 2 destroys
+ * only on those widgets destroyed by this particular dispatch.
+ *
+ */
+
+ if (app->destroy_count > starting_count)
+ _XtDoPhase2Destroy(app, dispatch_level);
+
+ app->dispatch_level = dispatch_level - 1;
+
+ if ((safe = _XtSafeToDestroy(app))) {
+ if (app->dpy_destroy_count != 0) _XtCloseDisplays(app);
+ if (app->free_bindings) _XtDoFreeBindings(app);
+ }
+ UNLOCK_APP(app);
+ LOCK_PROCESS;
+ if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts();
+ UNLOCK_PROCESS;
+ return was_dispatched;
+}
+
+/* ARGSUSED */
+static void GrabDestroyCallback(
+ Widget widget,
+ XtPointer closure,
+ XtPointer call_data)
+{
+ /* Remove widget from grab list if it destroyed */
+ XtRemoveGrab(widget);
+}
+
+static XtGrabRec *NewGrabRec(
+ Widget widget,
+ Boolean exclusive,
+ Boolean spring_loaded)
+{
+ register XtGrabList gl;
+
+ gl = XtNew(XtGrabRec);
+ gl->next = NULL;
+ gl->widget = widget;
+ gl->exclusive = exclusive;
+ gl->spring_loaded = spring_loaded;
+
+ return gl;
+}
+
+void XtAddGrab(
+ Widget widget,
+ _XtBoolean exclusive,
+ _XtBoolean spring_loaded)
+{
+ register XtGrabList gl;
+ XtGrabList *grabListPtr;
+ XtAppContext app = XtWidgetToApplicationContext(widget);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
+
+ if (spring_loaded && !exclusive) {
+ XtAppWarningMsg(app,
+ "grabError", "xtAddGrab", XtCXtToolkitError,
+ "XtAddGrab requires exclusive grab if spring_loaded is TRUE",
+ (String *) NULL, (Cardinal *) NULL);
+ exclusive = TRUE;
+ }
+
+ gl = NewGrabRec(widget, exclusive, spring_loaded);
+ gl->next = *grabListPtr;
+ *grabListPtr = gl;
+
+ XtAddCallback (widget, XtNdestroyCallback,
+ GrabDestroyCallback, (XtPointer) NULL);
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+}
+
+void XtRemoveGrab(
+ Widget widget)
+{
+ register XtGrabList gl;
+ register Boolean done;
+ XtGrabList *grabListPtr;
+ XtAppContext app = XtWidgetToApplicationContext(widget);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+
+ grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget)));
+
+ for (gl = *grabListPtr; gl != NULL; gl = gl->next) {
+ if (gl->widget == widget) break;
+ }
+
+ if (gl == NULL) {
+ XtAppWarningMsg(app,
+ "grabError","xtRemoveGrab",XtCXtToolkitError,
+ "XtRemoveGrab asked to remove a widget not on the list",
+ (String *)NULL, (Cardinal *)NULL);
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+ }
+
+ do {
+ gl = *grabListPtr;
+ done = (gl->widget == widget);
+ *grabListPtr = gl->next;
+ XtRemoveCallback(gl->widget, XtNdestroyCallback,
+ GrabDestroyCallback, (XtPointer)NULL);
+ XtFree((char *)gl);
+ } while (! done);
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+}
+
+void XtMainLoop(void)
+{
+ XtAppMainLoop(_XtDefaultAppContext());
+}
+
+void XtAppMainLoop(
+ XtAppContext app)
+{
+ XEvent event;
+
+ LOCK_APP(app);
+ do {
+ XtAppNextEvent(app, &event);
+#ifdef XTHREADS
+ /* assert(app == XtDisplayToApplicationContext(event.xany.display)); */
+#endif
+ XtDispatchEvent(&event);
+ } while(app->exit_flag == FALSE);
+ UNLOCK_APP(app);
+}
+
+void _XtFreeEventTable(
+ XtEventTable *event_table)
+{
+ register XtEventTable event;
+
+ event = *event_table;
+ while (event != NULL) {
+ register XtEventTable next = event->next;
+ XtFree((char *) event);
+ event = next;
+ }
+}
+
+Time XtLastTimestampProcessed(
+ Display *dpy)
+{
+ Time time;
+ DPY_TO_APPCON(dpy);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ time = _XtGetPerDisplay(dpy)->last_timestamp;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return(time);
+}
+
+XEvent* XtLastEventProcessed(
+ Display* dpy)
+{
+ XEvent* le = NULL;
+ DPY_TO_APPCON(dpy);
+
+ LOCK_APP(app);
+ le = &_XtGetPerDisplay(dpy)->last_event;
+ if (!le->xany.serial)
+ le = NULL;
+ UNLOCK_APP(app);
+ return le;
+}
+
+void _XtSendFocusEvent(
+ Widget child,
+ int type)
+{
+ child = XtIsWidget(child) ? child : _XtWindowedAncestor(child);
+ if (XtIsSensitive(child) && !child->core.being_destroyed
+ && XtIsRealized(child)
+ && (XtBuildEventMask(child) & FocusChangeMask))
+ {
+ XFocusChangeEvent event;
+ Display* dpy = XtDisplay (child);
+
+ event.type = type;
+ event.serial = LastKnownRequestProcessed(dpy);
+ event.send_event = True;
+ event.display = dpy;
+ event.window = XtWindow(child);
+ event.mode = NotifyNormal;
+ event.detail = NotifyAncestor;
+ if (XFilterEvent((XEvent*)&event, XtWindow(child)))
+ return;
+ XtDispatchEventToWidget(child, (XEvent*)&event);
+ }
+}
+
+static XtEventDispatchProc* NewDispatcherList(void)
+{
+ XtEventDispatchProc* l =
+ (XtEventDispatchProc*) __XtCalloc((Cardinal) 128,
+ (Cardinal)sizeof(XtEventDispatchProc));
+ return l;
+}
+
+XtEventDispatchProc XtSetEventDispatcher(
+ Display *dpy,
+ int event_type,
+ XtEventDispatchProc proc)
+{
+ XtEventDispatchProc *list;
+ XtEventDispatchProc old_proc;
+ register XtPerDisplay pd;
+ DPY_TO_APPCON(dpy);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ pd = _XtGetPerDisplay(dpy);
+
+ list = pd->dispatcher_list;
+ if (!list) {
+ if (proc) list = pd->dispatcher_list = NewDispatcherList();
+ else return _XtDefaultDispatcher;
+ }
+ old_proc = list[event_type];
+ list[event_type] = proc;
+ if (old_proc == NULL) old_proc = _XtDefaultDispatcher;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return old_proc;
+}
+
+void XtRegisterExtensionSelector(
+ Display *dpy,
+ int min_event_type,
+ int max_event_type,
+ XtExtensionSelectProc proc,
+ XtPointer client_data)
+{
+ ExtSelectRec *e;
+ XtPerDisplay pd;
+ int i;
+ DPY_TO_APPCON(dpy);
+
+ if (dpy == NULL) XtErrorMsg("nullDisplay",
+ "xtRegisterExtensionSelector", XtCXtToolkitError,
+ "XtRegisterExtensionSelector requires a non-NULL display",
+ (String *) NULL, (Cardinal *) NULL);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+ pd = _XtGetPerDisplay(dpy);
+
+ for (i = 0; i < pd->ext_select_count; i++) {
+ e = &pd->ext_select_list[i];
+ if (e->min == min_event_type && e->max == max_event_type) {
+ e->proc = proc;
+ e->client_data = client_data;
+ return;
+ }
+ if ((min_event_type >= e->min && min_event_type <= e->max) ||
+ (max_event_type >= e->min && max_event_type <= e->max)) {
+ XtErrorMsg("rangeError", "xtRegisterExtensionSelector",
+ XtCXtToolkitError,
+ "Attempt to register multiple selectors for one extension event type",
+ (String *) NULL, (Cardinal *) NULL);
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+ return;
+ }
+ }
+ pd->ext_select_count++;
+ pd->ext_select_list =
+ (ExtSelectRec *) XtRealloc((char *) pd->ext_select_list,
+ pd->ext_select_count * sizeof(ExtSelectRec));
+ for (i = pd->ext_select_count - 1; i > 0; i--) {
+ if (pd->ext_select_list[i-1].min > min_event_type) {
+ pd->ext_select_list[i] = pd->ext_select_list[i-1];
+ } else break;
+ }
+ pd->ext_select_list[i].min = min_event_type;
+ pd->ext_select_list[i].max = max_event_type;
+ pd->ext_select_list[i].proc = proc;
+ pd->ext_select_list[i].client_data = client_data;
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+}
+
+void _XtExtensionSelect(
+ Widget widget)
+{
+ int i;
+ XtPerDisplay pd;
+ WIDGET_TO_APPCON(widget);
+
+ LOCK_APP(app);
+ LOCK_PROCESS;
+
+ pd = _XtGetPerDisplay(XtDisplay(widget));
+
+ for (i = 0; i < pd->ext_select_count; i++) {
+ CallExtensionSelector(widget, pd->ext_select_list+i, FALSE);
+ }
+ UNLOCK_PROCESS;
+ UNLOCK_APP(app);
+}
|