Event.c revision 444c061a
1444c061aSmrg/* $Xorg: Event.c,v 1.5 2001/02/09 02:03:54 xorgcvs Exp $ */ 2444c061aSmrg 3444c061aSmrg/*********************************************************** 4444c061aSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, 5444c061aSmrgCopyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 6444c061aSmrg 7444c061aSmrg All Rights Reserved 8444c061aSmrg 9444c061aSmrgPermission to use, copy, modify, and distribute this software and its 10444c061aSmrgdocumentation for any purpose and without fee is hereby granted, 11444c061aSmrgprovided that the above copyright notice appear in all copies and that 12444c061aSmrgboth that copyright notice and this permission notice appear in 13444c061aSmrgsupporting documentation, and that the names of Digital or Sun not be 14444c061aSmrgused in advertising or publicity pertaining to distribution of the 15444c061aSmrgsoftware without specific, written prior permission. 16444c061aSmrg 17444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 18444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 19444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 20444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 21444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 22444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23444c061aSmrgSOFTWARE. 24444c061aSmrg 25444c061aSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26444c061aSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 27444c061aSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 28444c061aSmrgABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 29444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 30444c061aSmrgPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 31444c061aSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 32444c061aSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 33444c061aSmrg 34444c061aSmrg******************************************************************/ 35444c061aSmrg 36444c061aSmrg/* 37444c061aSmrg 38444c061aSmrgCopyright 1987, 1988, 1998 The Open Group 39444c061aSmrg 40444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 41444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 42444c061aSmrgthe above copyright notice appear in all copies and that both that 43444c061aSmrgcopyright notice and this permission notice appear in supporting 44444c061aSmrgdocumentation. 45444c061aSmrg 46444c061aSmrgThe above copyright notice and this permission notice shall be included in 47444c061aSmrgall copies or substantial portions of the Software. 48444c061aSmrg 49444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 53444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 54444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55444c061aSmrg 56444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 57444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 58444c061aSmrgin this Software without prior written authorization from The Open Group. 59444c061aSmrg 60444c061aSmrg*/ 61444c061aSmrg/* $XFree86: xc/lib/Xt/Event.c,v 3.10 2001/12/14 19:56:11 dawes Exp $ */ 62444c061aSmrg 63444c061aSmrg#ifdef HAVE_CONFIG_H 64444c061aSmrg#include <config.h> 65444c061aSmrg#endif 66444c061aSmrg#include "IntrinsicI.h" 67444c061aSmrg#include "Shell.h" 68444c061aSmrg#include "StringDefs.h" 69444c061aSmrg 70444c061aSmrgtypedef struct _XtEventRecExt { 71444c061aSmrg int type; 72444c061aSmrg XtPointer select_data[1]; /* actual dimension is [mask] */ 73444c061aSmrg} XtEventRecExt; 74444c061aSmrg 75444c061aSmrg#define EXT_TYPE(p) (((XtEventRecExt*) ((p)+1))->type) 76444c061aSmrg#define EXT_SELECT_DATA(p,n) (((XtEventRecExt*) ((p)+1))->select_data[n]) 77444c061aSmrg 78444c061aSmrg#define NonMaskableMask ((EventMask)0x80000000L) 79444c061aSmrg 80444c061aSmrg/* 81444c061aSmrg * These are definitions to make the code that handles exposure compresssion 82444c061aSmrg * easier to read. 83444c061aSmrg * 84444c061aSmrg * COMP_EXPOSE - The compression exposure field of "widget" 85444c061aSmrg * COMP_EXPOSE_TYPE - The type of compression (lower 4 bits of COMP_EXPOSE. 86444c061aSmrg * GRAPHICS_EXPOSE - TRUE if the widget wants graphics expose events 87444c061aSmrg * dispatched. 88444c061aSmrg * NO_EXPOSE - TRUE if the widget wants No expose events dispatched. 89444c061aSmrg */ 90444c061aSmrg 91444c061aSmrg#define COMP_EXPOSE (widget->core.widget_class->core_class.compress_exposure) 92444c061aSmrg#define COMP_EXPOSE_TYPE (COMP_EXPOSE & 0x0f) 93444c061aSmrg#define GRAPHICS_EXPOSE ((XtExposeGraphicsExpose & COMP_EXPOSE) || \ 94444c061aSmrg (XtExposeGraphicsExposeMerged & COMP_EXPOSE)) 95444c061aSmrg#define NO_EXPOSE (XtExposeNoExpose & COMP_EXPOSE) 96444c061aSmrg 97444c061aSmrgEventMask XtBuildEventMask( 98444c061aSmrg Widget widget) 99444c061aSmrg{ 100444c061aSmrg XtEventTable ev; 101444c061aSmrg EventMask mask = 0L; 102444c061aSmrg WIDGET_TO_APPCON(widget); 103444c061aSmrg 104444c061aSmrg LOCK_APP(app); 105444c061aSmrg for (ev = widget->core.event_table; ev != NULL; ev = ev->next) 106444c061aSmrg if (ev->select) { 107444c061aSmrg if (!ev->has_type_specifier) 108444c061aSmrg mask |= ev->mask; 109444c061aSmrg else { 110444c061aSmrg if (EXT_TYPE(ev) < LASTEvent) { 111444c061aSmrg Cardinal i; 112444c061aSmrg for (i = 0; i < ev->mask; i++) 113444c061aSmrg if (EXT_SELECT_DATA(ev, i)) 114444c061aSmrg mask |= *(EventMask*)EXT_SELECT_DATA(ev, i); 115444c061aSmrg } 116444c061aSmrg } 117444c061aSmrg } 118444c061aSmrg LOCK_PROCESS; 119444c061aSmrg if (widget->core.widget_class->core_class.expose != NULL) 120444c061aSmrg mask |= ExposureMask; 121444c061aSmrg if (widget->core.widget_class->core_class.visible_interest) 122444c061aSmrg mask |= VisibilityChangeMask; 123444c061aSmrg UNLOCK_PROCESS; 124444c061aSmrg if (widget->core.tm.translations) 125444c061aSmrg mask |= widget->core.tm.translations->eventMask; 126444c061aSmrg 127444c061aSmrg mask = mask & ~NonMaskableMask; 128444c061aSmrg UNLOCK_APP(app); 129444c061aSmrg return mask; 130444c061aSmrg} 131444c061aSmrg 132444c061aSmrgstatic void CallExtensionSelector( 133444c061aSmrg Widget widget, 134444c061aSmrg ExtSelectRec* rec, 135444c061aSmrg Boolean forceCall) 136444c061aSmrg{ 137444c061aSmrg XtEventRec* p; 138444c061aSmrg XtPointer* data; 139444c061aSmrg int* types; 140444c061aSmrg Cardinal i, count = 0; 141444c061aSmrg 142444c061aSmrg for (p = widget->core.event_table; p != NULL; p = p->next) 143444c061aSmrg if (p->has_type_specifier && 144444c061aSmrg EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max) 145444c061aSmrg count += p->mask; 146444c061aSmrg 147444c061aSmrg if (count == 0 && !forceCall) return; 148444c061aSmrg 149444c061aSmrg data = (XtPointer *) ALLOCATE_LOCAL(count * sizeof (XtPointer)); 150444c061aSmrg types = (int *) ALLOCATE_LOCAL(count * sizeof (int)); 151444c061aSmrg count = 0; 152444c061aSmrg 153444c061aSmrg for (p = widget->core.event_table; p != NULL; p = p->next) 154444c061aSmrg if (p->has_type_specifier && 155444c061aSmrg EXT_TYPE(p) >= rec->min && EXT_TYPE(p) <= rec->max) 156444c061aSmrg for (i =0; i < p->mask; i++) { 157444c061aSmrg types[count] = EXT_TYPE(p); 158444c061aSmrg data[count++] = EXT_SELECT_DATA(p, i); 159444c061aSmrg } 160444c061aSmrg 161444c061aSmrg (*rec->proc)(widget, types, data, count, rec->client_data); 162444c061aSmrg DEALLOCATE_LOCAL((char*) types); 163444c061aSmrg DEALLOCATE_LOCAL((char*) data); 164444c061aSmrg} 165444c061aSmrg 166444c061aSmrgstatic void 167444c061aSmrgRemoveEventHandler( 168444c061aSmrg Widget widget, 169444c061aSmrg XtPointer select_data, 170444c061aSmrg int type, 171444c061aSmrg Boolean has_type_specifier, 172444c061aSmrg Boolean other, 173444c061aSmrg XtEventHandler proc, 174444c061aSmrg XtPointer closure, 175444c061aSmrg Boolean raw) 176444c061aSmrg{ 177444c061aSmrg XtEventRec *p, **pp; 178444c061aSmrg EventMask eventMask, oldMask = XtBuildEventMask(widget); 179444c061aSmrg 180444c061aSmrg if (raw) raw = 1; 181444c061aSmrg pp = &widget->core.event_table; 182444c061aSmrg while ((p = *pp) && 183444c061aSmrg (p->proc != proc || p->closure != closure || p->select == raw || 184444c061aSmrg has_type_specifier != p->has_type_specifier || 185444c061aSmrg (has_type_specifier && EXT_TYPE(p) != type))) 186444c061aSmrg pp = &p->next; 187444c061aSmrg if (!p) return; 188444c061aSmrg 189444c061aSmrg /* un-register it */ 190444c061aSmrg if (!has_type_specifier) { 191444c061aSmrg eventMask = *(EventMask*)select_data; 192444c061aSmrg eventMask &= ~NonMaskableMask; 193444c061aSmrg if (other) 194444c061aSmrg eventMask |= NonMaskableMask; 195444c061aSmrg p->mask &= ~eventMask; 196444c061aSmrg } else { 197444c061aSmrg Cardinal i; 198444c061aSmrg /* p->mask specifies count of EXT_SELECT_DATA(p,i) 199444c061aSmrg * search through the list of selection data, if not found 200444c061aSmrg * dont remove this handler 201444c061aSmrg */ 202444c061aSmrg for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i);) i++; 203444c061aSmrg if (i == p->mask) return; 204444c061aSmrg if (p->mask == 1) p->mask = 0; 205444c061aSmrg else { 206444c061aSmrg p->mask--; 207444c061aSmrg while (i < p->mask) { 208444c061aSmrg EXT_SELECT_DATA(p,i) = EXT_SELECT_DATA(p, i+1); 209444c061aSmrg i++; 210444c061aSmrg } 211444c061aSmrg } 212444c061aSmrg } 213444c061aSmrg 214444c061aSmrg if (!p->mask) { /* delete it entirely */ 215444c061aSmrg *pp = p->next; 216444c061aSmrg XtFree((char *)p); 217444c061aSmrg } 218444c061aSmrg 219444c061aSmrg /* Reset select mask if realized and not raw. */ 220444c061aSmrg if ( !raw && XtIsRealized(widget) && !widget->core.being_destroyed) { 221444c061aSmrg EventMask mask = XtBuildEventMask(widget); 222444c061aSmrg Display* dpy = XtDisplay (widget); 223444c061aSmrg 224444c061aSmrg if (oldMask != mask) 225444c061aSmrg XSelectInput(dpy, XtWindow(widget), mask); 226444c061aSmrg 227444c061aSmrg if (has_type_specifier) { 228444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay(dpy); 229444c061aSmrg int i; 230444c061aSmrg for (i = 0; i < pd->ext_select_count; i++) { 231444c061aSmrg if (type >= pd->ext_select_list[i].min && 232444c061aSmrg type <= pd->ext_select_list[i].max) { 233444c061aSmrg CallExtensionSelector(widget, pd->ext_select_list+i, TRUE); 234444c061aSmrg break; 235444c061aSmrg } 236444c061aSmrg if (type < pd->ext_select_list[i].min) break; 237444c061aSmrg } 238444c061aSmrg } 239444c061aSmrg } 240444c061aSmrg} 241444c061aSmrg 242444c061aSmrg/* Function Name: AddEventHandler 243444c061aSmrg * Description: An Internal routine that does the actual work of 244444c061aSmrg * adding the event handlers. 245444c061aSmrg * Arguments: widget - widget to register an event handler for. 246444c061aSmrg * eventMask - events to mask for. 247444c061aSmrg * other - pass non maskable events to this proceedure. 248444c061aSmrg * proc - proceedure to register. 249444c061aSmrg * closure - data to pass to the event hander. 250444c061aSmrg * position - where to add this event handler. 251444c061aSmrg * force_new_position - If the element is already in the 252444c061aSmrg * list, this will force it to the 253444c061aSmrg * beginning or end depending on position. 254444c061aSmrg * raw - If FALSE call XSelectInput for events in mask. 255444c061aSmrg * Returns: none 256444c061aSmrg */ 257444c061aSmrg 258444c061aSmrgstatic void 259444c061aSmrgAddEventHandler( 260444c061aSmrg Widget widget, 261444c061aSmrg XtPointer select_data, 262444c061aSmrg int type, 263444c061aSmrg Boolean has_type_specifier, 264444c061aSmrg Boolean other, 265444c061aSmrg XtEventHandler proc, 266444c061aSmrg XtPointer closure, 267444c061aSmrg XtListPosition position, 268444c061aSmrg Boolean force_new_position, 269444c061aSmrg Boolean raw) 270444c061aSmrg{ 271444c061aSmrg register XtEventRec *p, **pp; 272444c061aSmrg EventMask oldMask = 0, eventMask = 0; 273444c061aSmrg 274444c061aSmrg if (!has_type_specifier) { 275444c061aSmrg eventMask = *(EventMask*)select_data & ~NonMaskableMask; 276444c061aSmrg if (other) eventMask |= NonMaskableMask; 277444c061aSmrg if (!eventMask) return; 278444c061aSmrg } else if (!type) return; 279444c061aSmrg 280444c061aSmrg if (XtIsRealized(widget) && !raw) oldMask = XtBuildEventMask(widget); 281444c061aSmrg 282444c061aSmrg if (raw) raw = 1; 283444c061aSmrg pp = &widget->core.event_table; 284444c061aSmrg while ((p = *pp) && 285444c061aSmrg (p->proc != proc || p->closure != closure || p->select == raw || 286444c061aSmrg has_type_specifier != p->has_type_specifier || 287444c061aSmrg (has_type_specifier && EXT_TYPE(p) != type))) 288444c061aSmrg pp = &p->next; 289444c061aSmrg 290444c061aSmrg if (!p) { /* New proc to add to list */ 291444c061aSmrg if (has_type_specifier) { 292444c061aSmrg p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec) + 293444c061aSmrg sizeof(XtEventRecExt)); 294444c061aSmrg EXT_TYPE(p) = type; 295444c061aSmrg EXT_SELECT_DATA(p,0) = select_data; 296444c061aSmrg p->mask = 1; 297444c061aSmrg p->has_type_specifier = True; 298444c061aSmrg } else { 299444c061aSmrg p = (XtEventRec*) __XtMalloc(sizeof(XtEventRec)); 300444c061aSmrg p->mask = eventMask; 301444c061aSmrg p->has_type_specifier = False; 302444c061aSmrg } 303444c061aSmrg p->proc = proc; 304444c061aSmrg p->closure = closure; 305444c061aSmrg p->select = ! raw; 306444c061aSmrg 307444c061aSmrg if (position == XtListHead) { 308444c061aSmrg p->next = widget->core.event_table; 309444c061aSmrg widget->core.event_table = p; 310444c061aSmrg pp = &widget->core.event_table; 311444c061aSmrg } else { 312444c061aSmrg *pp = p; 313444c061aSmrg p->next = NULL; 314444c061aSmrg } 315444c061aSmrg } 316444c061aSmrg else { 317444c061aSmrg if (force_new_position) { 318444c061aSmrg *pp = p->next; 319444c061aSmrg 320444c061aSmrg if (position == XtListHead) { 321444c061aSmrg p->next = widget->core.event_table; 322444c061aSmrg widget->core.event_table = p; 323444c061aSmrg } else { 324444c061aSmrg /* 325444c061aSmrg * Find the last element in the list. 326444c061aSmrg */ 327444c061aSmrg while (*pp) 328444c061aSmrg pp = &(*pp)->next; 329444c061aSmrg *pp = p; 330444c061aSmrg p->next = NULL; 331444c061aSmrg } 332444c061aSmrg } 333444c061aSmrg 334444c061aSmrg if (!has_type_specifier) 335444c061aSmrg p->mask |= eventMask; 336444c061aSmrg else { 337444c061aSmrg Cardinal i; 338444c061aSmrg /* p->mask specifies count of EXT_SELECT_DATA(p,i) */ 339444c061aSmrg for (i = 0; i < p->mask && select_data != EXT_SELECT_DATA(p,i); ) 340444c061aSmrg i++; 341444c061aSmrg if (i == p->mask) { 342444c061aSmrg p = (XtEventRec*) XtRealloc((char*)p, 343444c061aSmrg sizeof(XtEventRec) + 344444c061aSmrg sizeof(XtEventRecExt) + 345444c061aSmrg p->mask * sizeof(XtPointer)); 346444c061aSmrg EXT_SELECT_DATA(p,i) = select_data; 347444c061aSmrg p->mask++; 348444c061aSmrg *pp = p; 349444c061aSmrg } 350444c061aSmrg } 351444c061aSmrg } 352444c061aSmrg 353444c061aSmrg if (XtIsRealized(widget) && !raw) { 354444c061aSmrg EventMask mask = XtBuildEventMask(widget); 355444c061aSmrg Display* dpy = XtDisplay (widget); 356444c061aSmrg 357444c061aSmrg if (oldMask != mask) 358444c061aSmrg XSelectInput(dpy, XtWindow(widget), mask); 359444c061aSmrg 360444c061aSmrg if (has_type_specifier) { 361444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay (dpy); 362444c061aSmrg int i; 363444c061aSmrg for (i = 0; i < pd->ext_select_count; i++) { 364444c061aSmrg if (type >= pd->ext_select_list[i].min && 365444c061aSmrg type <= pd->ext_select_list[i].max) { 366444c061aSmrg CallExtensionSelector(widget, pd->ext_select_list+i, FALSE); 367444c061aSmrg break; 368444c061aSmrg } 369444c061aSmrg if (type < pd->ext_select_list[i].min) break; 370444c061aSmrg } 371444c061aSmrg } 372444c061aSmrg } 373444c061aSmrg} 374444c061aSmrg 375444c061aSmrgvoid XtRemoveEventHandler( 376444c061aSmrg Widget widget, 377444c061aSmrg EventMask eventMask, 378444c061aSmrg _XtBoolean other, 379444c061aSmrg XtEventHandler proc, 380444c061aSmrg XtPointer closure) 381444c061aSmrg{ 382444c061aSmrg WIDGET_TO_APPCON(widget); 383444c061aSmrg LOCK_APP(app); 384444c061aSmrg RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, 385444c061aSmrg other, proc, closure, FALSE); 386444c061aSmrg UNLOCK_APP(app); 387444c061aSmrg} 388444c061aSmrg 389444c061aSmrgvoid XtAddEventHandler( 390444c061aSmrg Widget widget, 391444c061aSmrg EventMask eventMask, 392444c061aSmrg _XtBoolean other, 393444c061aSmrg XtEventHandler proc, 394444c061aSmrg XtPointer closure) 395444c061aSmrg{ 396444c061aSmrg WIDGET_TO_APPCON(widget); 397444c061aSmrg LOCK_APP(app); 398444c061aSmrg AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, 399444c061aSmrg proc, closure, XtListTail, FALSE, FALSE); 400444c061aSmrg UNLOCK_APP(app); 401444c061aSmrg} 402444c061aSmrg 403444c061aSmrgvoid XtInsertEventHandler( 404444c061aSmrg Widget widget, 405444c061aSmrg EventMask eventMask, 406444c061aSmrg _XtBoolean other, 407444c061aSmrg XtEventHandler proc, 408444c061aSmrg XtPointer closure, 409444c061aSmrg XtListPosition position) 410444c061aSmrg{ 411444c061aSmrg WIDGET_TO_APPCON(widget); 412444c061aSmrg LOCK_APP(app); 413444c061aSmrg AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, 414444c061aSmrg proc, closure, position, TRUE, FALSE); 415444c061aSmrg UNLOCK_APP(app); 416444c061aSmrg} 417444c061aSmrg 418444c061aSmrgvoid XtRemoveRawEventHandler( 419444c061aSmrg Widget widget, 420444c061aSmrg EventMask eventMask, 421444c061aSmrg _XtBoolean other, 422444c061aSmrg XtEventHandler proc, 423444c061aSmrg XtPointer closure) 424444c061aSmrg{ 425444c061aSmrg WIDGET_TO_APPCON(widget); 426444c061aSmrg LOCK_APP(app); 427444c061aSmrg RemoveEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, 428444c061aSmrg other, proc, closure, TRUE); 429444c061aSmrg UNLOCK_APP(app); 430444c061aSmrg} 431444c061aSmrg 432444c061aSmrgvoid XtInsertRawEventHandler( 433444c061aSmrg Widget widget, 434444c061aSmrg EventMask eventMask, 435444c061aSmrg _XtBoolean other, 436444c061aSmrg XtEventHandler proc, 437444c061aSmrg XtPointer closure, 438444c061aSmrg XtListPosition position) 439444c061aSmrg{ 440444c061aSmrg WIDGET_TO_APPCON(widget); 441444c061aSmrg LOCK_APP(app); 442444c061aSmrg AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, 443444c061aSmrg proc, closure, position, TRUE, TRUE); 444444c061aSmrg UNLOCK_APP(app); 445444c061aSmrg} 446444c061aSmrg 447444c061aSmrgvoid XtAddRawEventHandler( 448444c061aSmrg Widget widget, 449444c061aSmrg EventMask eventMask, 450444c061aSmrg _XtBoolean other, 451444c061aSmrg XtEventHandler proc, 452444c061aSmrg XtPointer closure) 453444c061aSmrg{ 454444c061aSmrg WIDGET_TO_APPCON(widget); 455444c061aSmrg LOCK_APP(app); 456444c061aSmrg AddEventHandler(widget, (XtPointer) &eventMask, 0, FALSE, other, 457444c061aSmrg proc, closure, XtListTail, FALSE, TRUE); 458444c061aSmrg UNLOCK_APP(app); 459444c061aSmrg} 460444c061aSmrg 461444c061aSmrgvoid XtRemoveEventTypeHandler( 462444c061aSmrg Widget widget, 463444c061aSmrg int type, 464444c061aSmrg XtPointer select_data, 465444c061aSmrg XtEventHandler proc, 466444c061aSmrg XtPointer closure) 467444c061aSmrg{ 468444c061aSmrg WIDGET_TO_APPCON(widget); 469444c061aSmrg LOCK_APP(app); 470444c061aSmrg RemoveEventHandler(widget, select_data, type, TRUE, 471444c061aSmrg FALSE, proc, closure, FALSE); 472444c061aSmrg UNLOCK_APP(app); 473444c061aSmrg} 474444c061aSmrg 475444c061aSmrgvoid XtInsertEventTypeHandler( 476444c061aSmrg Widget widget, 477444c061aSmrg int type, 478444c061aSmrg XtPointer select_data, 479444c061aSmrg XtEventHandler proc, 480444c061aSmrg XtPointer closure, 481444c061aSmrg XtListPosition position) 482444c061aSmrg{ 483444c061aSmrg WIDGET_TO_APPCON(widget); 484444c061aSmrg LOCK_APP(app); 485444c061aSmrg AddEventHandler(widget, select_data, type, TRUE, FALSE, 486444c061aSmrg proc, closure, position, TRUE, FALSE); 487444c061aSmrg UNLOCK_APP(app); 488444c061aSmrg} 489444c061aSmrg 490444c061aSmrgtypedef struct _WWPair { 491444c061aSmrg struct _WWPair *next; 492444c061aSmrg Window window; 493444c061aSmrg Widget widget; 494444c061aSmrg} *WWPair; 495444c061aSmrg 496444c061aSmrgtypedef struct _WWTable { 497444c061aSmrg unsigned int mask; /* size of hash table - 1 */ 498444c061aSmrg unsigned int rehash; /* mask - 2 */ 499444c061aSmrg unsigned int occupied; /* number of occupied entries */ 500444c061aSmrg unsigned int fakes; /* number occupied by WWfake */ 501444c061aSmrg Widget *entries; /* the entries */ 502444c061aSmrg WWPair pairs; /* bogus entries */ 503444c061aSmrg} *WWTable; 504444c061aSmrg 505444c061aSmrgstatic const WidgetRec WWfake; /* placeholder for deletions */ 506444c061aSmrg 507444c061aSmrg#define WWHASH(tab,win) ((win) & tab->mask) 508444c061aSmrg#define WWREHASHVAL(tab,win) ((((win) % tab->rehash) + 2) | 1) 509444c061aSmrg#define WWREHASH(tab,idx,rehash) ((idx + rehash) & tab->mask) 510444c061aSmrg#define WWTABLE(display) (_XtGetPerDisplay(display)->WWtable) 511444c061aSmrg 512444c061aSmrgstatic void ExpandWWTable(WWTable); 513444c061aSmrg 514444c061aSmrgvoid XtRegisterDrawable( 515444c061aSmrg Display* display, 516444c061aSmrg Drawable drawable, 517444c061aSmrg Widget widget) 518444c061aSmrg{ 519444c061aSmrg WWTable tab; 520444c061aSmrg int idx, rehash; 521444c061aSmrg Widget entry; 522444c061aSmrg Window window = (Window) drawable; 523444c061aSmrg WIDGET_TO_APPCON(widget); 524444c061aSmrg 525444c061aSmrg LOCK_APP(app); 526444c061aSmrg LOCK_PROCESS; 527444c061aSmrg tab = WWTABLE(display); 528444c061aSmrg if (window != XtWindow(widget)) { 529444c061aSmrg WWPair pair; 530444c061aSmrg pair = XtNew(struct _WWPair); 531444c061aSmrg pair->next = tab->pairs; 532444c061aSmrg pair->window = window; 533444c061aSmrg pair->widget = widget; 534444c061aSmrg tab->pairs = pair; 535444c061aSmrg UNLOCK_PROCESS; 536444c061aSmrg UNLOCK_APP(app); 537444c061aSmrg return; 538444c061aSmrg } 539444c061aSmrg if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) 540444c061aSmrg ExpandWWTable(tab); 541444c061aSmrg 542444c061aSmrg idx = WWHASH(tab, window); 543444c061aSmrg if ((entry = tab->entries[idx]) && entry != &WWfake) { 544444c061aSmrg rehash = WWREHASHVAL(tab, window); 545444c061aSmrg do { 546444c061aSmrg idx = WWREHASH(tab, idx, rehash); 547444c061aSmrg } while ((entry = tab->entries[idx]) && entry != &WWfake); 548444c061aSmrg } 549444c061aSmrg if (!entry) 550444c061aSmrg tab->occupied++; 551444c061aSmrg else if (entry == &WWfake) 552444c061aSmrg tab->fakes--; 553444c061aSmrg tab->entries[idx] = widget; 554444c061aSmrg UNLOCK_PROCESS; 555444c061aSmrg UNLOCK_APP(app); 556444c061aSmrg} 557444c061aSmrg 558444c061aSmrgvoid XtUnregisterDrawable( 559444c061aSmrg Display* display, 560444c061aSmrg Drawable drawable) 561444c061aSmrg{ 562444c061aSmrg WWTable tab; 563444c061aSmrg int idx, rehash; 564444c061aSmrg Widget entry; 565444c061aSmrg Window window = (Window) drawable; 566444c061aSmrg Widget widget = XtWindowToWidget (display, window); 567444c061aSmrg DPY_TO_APPCON(display); 568444c061aSmrg 569444c061aSmrg if (widget == NULL) return; 570444c061aSmrg 571444c061aSmrg LOCK_APP(app); 572444c061aSmrg LOCK_PROCESS; 573444c061aSmrg tab = WWTABLE(display); 574444c061aSmrg if (window != XtWindow(widget)) { 575444c061aSmrg WWPair *prev, pair; 576444c061aSmrg 577444c061aSmrg prev = &tab->pairs; 578444c061aSmrg while ((pair = *prev) && pair->window != window) 579444c061aSmrg prev = &pair->next; 580444c061aSmrg if (pair) { 581444c061aSmrg *prev = pair->next; 582444c061aSmrg XtFree((char *)pair); 583444c061aSmrg } 584444c061aSmrg UNLOCK_PROCESS; 585444c061aSmrg UNLOCK_APP(app); 586444c061aSmrg return; 587444c061aSmrg } 588444c061aSmrg idx = WWHASH(tab, window); 589444c061aSmrg if ((entry = tab->entries[idx])) { 590444c061aSmrg if (entry != widget) { 591444c061aSmrg rehash = WWREHASHVAL(tab, window); 592444c061aSmrg do { 593444c061aSmrg idx = WWREHASH(tab, idx, rehash); 594444c061aSmrg if (!(entry = tab->entries[idx])) { 595444c061aSmrg UNLOCK_PROCESS; 596444c061aSmrg UNLOCK_APP(app); 597444c061aSmrg return; 598444c061aSmrg } 599444c061aSmrg } while (entry != widget); 600444c061aSmrg } 601444c061aSmrg tab->entries[idx] = (Widget)&WWfake; 602444c061aSmrg tab->fakes++; 603444c061aSmrg } 604444c061aSmrg UNLOCK_PROCESS; 605444c061aSmrg UNLOCK_APP(app); 606444c061aSmrg} 607444c061aSmrg 608444c061aSmrgstatic void ExpandWWTable( 609444c061aSmrg register WWTable tab) 610444c061aSmrg{ 611444c061aSmrg unsigned int oldmask; 612444c061aSmrg register Widget *oldentries, *entries; 613444c061aSmrg register Cardinal oldidx, newidx, rehash; 614444c061aSmrg register Widget entry; 615444c061aSmrg 616444c061aSmrg LOCK_PROCESS; 617444c061aSmrg oldmask = tab->mask; 618444c061aSmrg oldentries = tab->entries; 619444c061aSmrg tab->occupied -= tab->fakes; 620444c061aSmrg tab->fakes = 0; 621444c061aSmrg if ((tab->occupied + (tab->occupied >> 2)) > tab->mask) { 622444c061aSmrg tab->mask = (tab->mask << 1) + 1; 623444c061aSmrg tab->rehash = tab->mask - 2; 624444c061aSmrg } 625444c061aSmrg entries = tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget)); 626444c061aSmrg for (oldidx = 0; oldidx <= oldmask; oldidx++) { 627444c061aSmrg if ((entry = oldentries[oldidx]) && entry != &WWfake) { 628444c061aSmrg newidx = WWHASH(tab, XtWindow(entry)); 629444c061aSmrg if (entries[newidx]) { 630444c061aSmrg rehash = WWREHASHVAL(tab, XtWindow(entry)); 631444c061aSmrg do { 632444c061aSmrg newidx = WWREHASH(tab, newidx, rehash); 633444c061aSmrg } while (entries[newidx]); 634444c061aSmrg } 635444c061aSmrg entries[newidx] = entry; 636444c061aSmrg } 637444c061aSmrg } 638444c061aSmrg XtFree((char *)oldentries); 639444c061aSmrg UNLOCK_PROCESS; 640444c061aSmrg} 641444c061aSmrg 642444c061aSmrgWidget XtWindowToWidget( 643444c061aSmrg register Display *display, 644444c061aSmrg register Window window) 645444c061aSmrg{ 646444c061aSmrg register WWTable tab; 647444c061aSmrg register int idx, rehash; 648444c061aSmrg register Widget entry; 649444c061aSmrg WWPair pair; 650444c061aSmrg DPY_TO_APPCON(display); 651444c061aSmrg 652444c061aSmrg if (!window) return NULL; 653444c061aSmrg 654444c061aSmrg LOCK_APP(app); 655444c061aSmrg LOCK_PROCESS; 656444c061aSmrg tab = WWTABLE(display); 657444c061aSmrg idx = WWHASH(tab, window); 658444c061aSmrg if ((entry = tab->entries[idx]) && XtWindow(entry) != window) { 659444c061aSmrg rehash = WWREHASHVAL(tab, window); 660444c061aSmrg do { 661444c061aSmrg idx = WWREHASH(tab, idx, rehash); 662444c061aSmrg } while ((entry = tab->entries[idx]) && XtWindow(entry) != window); 663444c061aSmrg } 664444c061aSmrg if (entry) { 665444c061aSmrg UNLOCK_PROCESS; 666444c061aSmrg UNLOCK_APP(app); 667444c061aSmrg return entry; 668444c061aSmrg } 669444c061aSmrg for (pair = tab->pairs; pair; pair = pair->next) { 670444c061aSmrg if (pair->window == window) { 671444c061aSmrg entry = pair->widget; 672444c061aSmrg UNLOCK_PROCESS; 673444c061aSmrg UNLOCK_APP(app); 674444c061aSmrg return entry; 675444c061aSmrg } 676444c061aSmrg } 677444c061aSmrg UNLOCK_PROCESS; 678444c061aSmrg UNLOCK_APP(app); 679444c061aSmrg return NULL; 680444c061aSmrg} 681444c061aSmrg 682444c061aSmrgvoid _XtAllocWWTable( 683444c061aSmrg XtPerDisplay pd) 684444c061aSmrg{ 685444c061aSmrg register WWTable tab; 686444c061aSmrg 687444c061aSmrg tab = (WWTable) __XtMalloc(sizeof(struct _WWTable)); 688444c061aSmrg tab->mask = 0x7f; 689444c061aSmrg tab->rehash = tab->mask - 2; 690444c061aSmrg tab->entries = (Widget *) __XtCalloc(tab->mask+1, sizeof(Widget)); 691444c061aSmrg tab->occupied = 0; 692444c061aSmrg tab->fakes = 0; 693444c061aSmrg tab->pairs = NULL; 694444c061aSmrg pd->WWtable = tab; 695444c061aSmrg} 696444c061aSmrg 697444c061aSmrgvoid _XtFreeWWTable( 698444c061aSmrg register XtPerDisplay pd) 699444c061aSmrg{ 700444c061aSmrg register WWPair pair, next; 701444c061aSmrg 702444c061aSmrg for (pair = pd->WWtable->pairs; pair; pair = next) { 703444c061aSmrg next = pair->next; 704444c061aSmrg XtFree((char *)pair); 705444c061aSmrg } 706444c061aSmrg XtFree((char *)pd->WWtable->entries); 707444c061aSmrg XtFree((char *)pd->WWtable); 708444c061aSmrg} 709444c061aSmrg 710444c061aSmrg#define EHMAXSIZE 25 /* do not make whopping big */ 711444c061aSmrg 712444c061aSmrgstatic Boolean CallEventHandlers( 713444c061aSmrg Widget widget, 714444c061aSmrg XEvent *event, 715444c061aSmrg EventMask mask) 716444c061aSmrg{ 717444c061aSmrg register XtEventRec *p; 718444c061aSmrg XtEventHandler *proc; 719444c061aSmrg XtPointer *closure; 720444c061aSmrg XtEventHandler procs[EHMAXSIZE]; 721444c061aSmrg XtPointer closures[EHMAXSIZE]; 722444c061aSmrg Boolean cont_to_disp = True; 723444c061aSmrg int i, numprocs; 724444c061aSmrg 725444c061aSmrg /* Have to copy the procs into an array, because one of them might 726444c061aSmrg * call XtRemoveEventHandler, which would break our linked list. */ 727444c061aSmrg 728444c061aSmrg numprocs = 0; 729444c061aSmrg for (p=widget->core.event_table; p; p = p->next) { 730444c061aSmrg if ((!p->has_type_specifier && (mask & p->mask)) || 731444c061aSmrg (p->has_type_specifier && event->type == EXT_TYPE(p))) 732444c061aSmrg numprocs++; 733444c061aSmrg } 734444c061aSmrg if (numprocs > EHMAXSIZE) { 735444c061aSmrg proc = (XtEventHandler *)__XtMalloc(numprocs * (sizeof(XtEventHandler) + 736444c061aSmrg sizeof(XtPointer))); 737444c061aSmrg closure = (XtPointer *)(proc + numprocs); 738444c061aSmrg } else { 739444c061aSmrg proc = procs; 740444c061aSmrg closure = closures; 741444c061aSmrg } 742444c061aSmrg numprocs = 0; 743444c061aSmrg for (p=widget->core.event_table; p; p = p->next) { 744444c061aSmrg if ((!p->has_type_specifier && (mask & p->mask)) || 745444c061aSmrg (p->has_type_specifier && event->type == EXT_TYPE(p))) { 746444c061aSmrg proc[numprocs] = p->proc; 747444c061aSmrg closure[numprocs] = p->closure; 748444c061aSmrg numprocs++; 749444c061aSmrg } 750444c061aSmrg } 751444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc: 752444c061aSmrg Selection.c:ReqCleanup, 753444c061aSmrg "Shell.c":EventHandler, 754444c061aSmrg PassivGrab.c:ActiveHandler, 755444c061aSmrg PassivGrab.c:RealizeHandler, 756444c061aSmrg Keyboard.c:QueryEventMask, 757444c061aSmrg _XtHandleFocus, 758444c061aSmrg Selection.c:HandleSelectionReplies, 759444c061aSmrg Selection.c:HandleGetIncrement, 760444c061aSmrg Selection.c:HandleIncremental, 761444c061aSmrg Selection.c:HandlePropertyGone, 762444c061aSmrg Selection.c:HandleSelectionEvents 763444c061aSmrg */ 764444c061aSmrg for (i = 0; i < numprocs && cont_to_disp; i++) 765444c061aSmrg (*(proc[i]))(widget, closure[i], event, &cont_to_disp); 766444c061aSmrg if (numprocs > EHMAXSIZE) 767444c061aSmrg XtFree((char *)proc); 768444c061aSmrg return cont_to_disp; 769444c061aSmrg} 770444c061aSmrg 771444c061aSmrgstatic void CompressExposures(XEvent *, Widget); 772444c061aSmrg 773444c061aSmrg#define KnownButtons (Button1MotionMask|Button2MotionMask|Button3MotionMask|\ 774444c061aSmrg Button4MotionMask|Button5MotionMask) 775444c061aSmrg 776444c061aSmrg/* keep this SMALL to avoid blowing stack cache! */ 777444c061aSmrg/* because some compilers allocate all local locals on procedure entry */ 778444c061aSmrg#define EHSIZE 4 779444c061aSmrg 780444c061aSmrgBoolean XtDispatchEventToWidget( 781444c061aSmrg Widget widget, 782444c061aSmrg XEvent* event) 783444c061aSmrg{ 784444c061aSmrg register XtEventRec *p; 785444c061aSmrg Boolean was_dispatched = False; 786444c061aSmrg Boolean call_tm = False; 787444c061aSmrg Boolean cont_to_disp; 788444c061aSmrg EventMask mask; 789444c061aSmrg WIDGET_TO_APPCON(widget); 790444c061aSmrg 791444c061aSmrg LOCK_APP(app); 792444c061aSmrg 793444c061aSmrg mask = _XtConvertTypeToMask(event->type); 794444c061aSmrg if (event->type == MotionNotify) 795444c061aSmrg mask |= (event->xmotion.state & KnownButtons); 796444c061aSmrg 797444c061aSmrg LOCK_PROCESS; 798444c061aSmrg if ( (mask == ExposureMask) || 799444c061aSmrg ((event->type == NoExpose) && NO_EXPOSE) || 800444c061aSmrg ((event->type == GraphicsExpose) && GRAPHICS_EXPOSE) ) { 801444c061aSmrg 802444c061aSmrg if (widget->core.widget_class->core_class.expose != NULL ) { 803444c061aSmrg 804444c061aSmrg /* We need to mask off the bits that could contain the information 805444c061aSmrg * about whether or not we desire Graphics and NoExpose events. */ 806444c061aSmrg 807444c061aSmrg if ( (COMP_EXPOSE_TYPE == XtExposeNoCompress) || 808444c061aSmrg (event->type == NoExpose) ) 809444c061aSmrg 810444c061aSmrg (*widget->core.widget_class->core_class.expose) 811444c061aSmrg (widget, event, (Region)NULL); 812444c061aSmrg else { 813444c061aSmrg CompressExposures(event, widget); 814444c061aSmrg } 815444c061aSmrg was_dispatched = True; 816444c061aSmrg } 817444c061aSmrg } 818444c061aSmrg 819444c061aSmrg if ((mask == VisibilityChangeMask) && 820444c061aSmrg XtClass(widget)->core_class.visible_interest) { 821444c061aSmrg was_dispatched = True; 822444c061aSmrg /* our visibility just changed... */ 823444c061aSmrg switch (((XVisibilityEvent *)event)->state) { 824444c061aSmrg case VisibilityUnobscured: 825444c061aSmrg widget->core.visible = TRUE; 826444c061aSmrg break; 827444c061aSmrg 828444c061aSmrg case VisibilityPartiallyObscured: 829444c061aSmrg /* what do we want to say here? */ 830444c061aSmrg /* well... some of us is visible */ 831444c061aSmrg widget->core.visible = TRUE; 832444c061aSmrg break; 833444c061aSmrg 834444c061aSmrg case VisibilityFullyObscured: 835444c061aSmrg widget->core.visible = FALSE; 836444c061aSmrg /* do we want to mark our children obscured? */ 837444c061aSmrg break; 838444c061aSmrg } 839444c061aSmrg } 840444c061aSmrg UNLOCK_PROCESS; 841444c061aSmrg 842444c061aSmrg /* to maintain "copy" semantics we check TM now but call later */ 843444c061aSmrg if (widget->core.tm.translations && 844444c061aSmrg (mask & widget->core.tm.translations->eventMask)) 845444c061aSmrg call_tm = True; 846444c061aSmrg 847444c061aSmrg cont_to_disp = True; 848444c061aSmrg p=widget->core.event_table; 849444c061aSmrg if (p) { 850444c061aSmrg if (p->next) { 851444c061aSmrg XtEventHandler proc[EHSIZE]; 852444c061aSmrg XtPointer closure[EHSIZE]; 853444c061aSmrg int numprocs = 0; 854444c061aSmrg 855444c061aSmrg /* Have to copy the procs into an array, because one of them might 856444c061aSmrg * call XtRemoveEventHandler, which would break our linked list. */ 857444c061aSmrg 858444c061aSmrg for (; p; p = p->next) { 859444c061aSmrg if ((!p->has_type_specifier && (mask & p->mask)) || 860444c061aSmrg (p->has_type_specifier && event->type == EXT_TYPE(p))) { 861444c061aSmrg if (numprocs >= EHSIZE) 862444c061aSmrg break; 863444c061aSmrg proc[numprocs] = p->proc; 864444c061aSmrg closure[numprocs] = p->closure; 865444c061aSmrg numprocs++; 866444c061aSmrg } 867444c061aSmrg } 868444c061aSmrg if (numprocs) { 869444c061aSmrg if (p) { 870444c061aSmrg cont_to_disp = CallEventHandlers(widget, event, mask); 871444c061aSmrg } else { 872444c061aSmrg int i; 873444c061aSmrg for (i = 0; i < numprocs && cont_to_disp; i++) 874444c061aSmrg (*(proc[i]))(widget, closure[i], event, &cont_to_disp); 875444c061aSmrg/* FUNCTIONS CALLED THROUGH POINTER proc: 876444c061aSmrg Selection.c:ReqCleanup, 877444c061aSmrg "Shell.c":EventHandler, 878444c061aSmrg PassivGrab.c:ActiveHandler, 879444c061aSmrg PassivGrab.c:RealizeHandler, 880444c061aSmrg Keyboard.c:QueryEventMask, 881444c061aSmrg _XtHandleFocus, 882444c061aSmrg Selection.c:HandleSelectionReplies, 883444c061aSmrg Selection.c:HandleGetIncrement, 884444c061aSmrg Selection.c:HandleIncremental, 885444c061aSmrg Selection.c:HandlePropertyGone, 886444c061aSmrg Selection.c:HandleSelectionEvents 887444c061aSmrg */ 888444c061aSmrg } 889444c061aSmrg was_dispatched = True; 890444c061aSmrg } 891444c061aSmrg } else if ((!p->has_type_specifier && (mask & p->mask)) || 892444c061aSmrg (p->has_type_specifier && event->type == EXT_TYPE(p))) { 893444c061aSmrg (*p->proc)(widget, p->closure, event, &cont_to_disp); 894444c061aSmrg was_dispatched = True; 895444c061aSmrg } 896444c061aSmrg } 897444c061aSmrg if (call_tm && cont_to_disp) 898444c061aSmrg _XtTranslateEvent(widget, event); 899444c061aSmrg UNLOCK_APP(app); 900444c061aSmrg return (was_dispatched|call_tm); 901444c061aSmrg} 902444c061aSmrg 903444c061aSmrg/* 904444c061aSmrg * This structure is passed into the check exposure proc. 905444c061aSmrg */ 906444c061aSmrg 907444c061aSmrgtypedef struct _CheckExposeInfo { 908444c061aSmrg int type1, type2; /* Types of events to check for. */ 909444c061aSmrg Boolean maximal; /* Ignore non-exposure events? */ 910444c061aSmrg Boolean non_matching; /* Was there an event that did not 911444c061aSmrg match either type? */ 912444c061aSmrg Window window; /* Window to match. */ 913444c061aSmrg} CheckExposeInfo; 914444c061aSmrg 915444c061aSmrg#define GetCount(ev) (((XExposeEvent *)(ev))->count) 916444c061aSmrg 917444c061aSmrgstatic void SendExposureEvent(XEvent *, Widget, XtPerDisplay); 918444c061aSmrgstatic Bool CheckExposureEvent(Display *, XEvent *, char *); 919444c061aSmrgstatic void AddExposureToRectangularRegion(XEvent *, Region); 920444c061aSmrg 921444c061aSmrg/* Function Name: CompressExposures 922444c061aSmrg * Description: Handles all exposure compression 923444c061aSmrg * Arguments: event - the xevent that is to be dispatched 924444c061aSmrg * widget - the widget that this event occured in. 925444c061aSmrg * Returns: none. 926444c061aSmrg * 927444c061aSmrg * NOTE: Event must be of type Expose or GraphicsExpose. 928444c061aSmrg */ 929444c061aSmrg 930444c061aSmrgstatic void 931444c061aSmrgCompressExposures( 932444c061aSmrgXEvent * event, 933444c061aSmrgWidget widget) 934444c061aSmrg{ 935444c061aSmrg CheckExposeInfo info; 936444c061aSmrg int count; 937444c061aSmrg Display* dpy = XtDisplay (widget); 938444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay(dpy); 939444c061aSmrg XtEnum comp_expose; 940444c061aSmrg XtEnum comp_expose_type; 941444c061aSmrg Boolean no_region; 942444c061aSmrg 943444c061aSmrg LOCK_PROCESS; 944444c061aSmrg comp_expose = COMP_EXPOSE; 945444c061aSmrg UNLOCK_PROCESS; 946444c061aSmrg comp_expose_type = comp_expose & 0x0f; 947444c061aSmrg no_region = ((comp_expose & XtExposeNoRegion) ? True : False); 948444c061aSmrg 949444c061aSmrg if (no_region) 950444c061aSmrg AddExposureToRectangularRegion(event, pd->region); 951444c061aSmrg else 952444c061aSmrg XtAddExposureToRegion(event, pd->region); 953444c061aSmrg 954444c061aSmrg if ( GetCount(event) != 0 ) 955444c061aSmrg return; 956444c061aSmrg 957444c061aSmrg if ((comp_expose_type == XtExposeCompressSeries) || 958444c061aSmrg (XEventsQueued(dpy, QueuedAfterReading) == 0)) { 959444c061aSmrg SendExposureEvent(event, widget, pd); 960444c061aSmrg return; 961444c061aSmrg } 962444c061aSmrg 963444c061aSmrg if (comp_expose & XtExposeGraphicsExposeMerged) { 964444c061aSmrg info.type1 = Expose; 965444c061aSmrg info.type2 = GraphicsExpose; 966444c061aSmrg } 967444c061aSmrg else { 968444c061aSmrg info.type1 = event->type; 969444c061aSmrg info.type2 = 0; 970444c061aSmrg } 971444c061aSmrg info.maximal = (comp_expose_type == XtExposeCompressMaximal); 972444c061aSmrg info.non_matching = FALSE; 973444c061aSmrg info.window = XtWindow(widget); 974444c061aSmrg 975444c061aSmrg/* 976444c061aSmrg * We have to be very careful here not to hose down the processor 977444c061aSmrg * when blocking until count gets to zero. 978444c061aSmrg * 979444c061aSmrg * First, check to see if there are any events in the queue for this 980444c061aSmrg * widget, and of the correct type. 981444c061aSmrg * 982444c061aSmrg * Once we cannot find any more events, check to see that count is zero. 983444c061aSmrg * If it is not then block until we get another exposure event. 984444c061aSmrg * 985444c061aSmrg * If we find no more events, and count on the last one we saw was zero we 986444c061aSmrg * we can be sure that all events have been processed. 987444c061aSmrg * 988444c061aSmrg * Unfortunately, we wind up having to look at the entire queue 989444c061aSmrg * event if we're not doing Maximal compression, due to the 990444c061aSmrg * semantics of XCheckIfEvent (we can't abort without re-ordering 991444c061aSmrg * the event queue as a side-effect). 992444c061aSmrg */ 993444c061aSmrg 994444c061aSmrg count = 0; 995444c061aSmrg while (TRUE) { 996444c061aSmrg XEvent event_return; 997444c061aSmrg 998444c061aSmrg if (XCheckIfEvent(dpy, &event_return, 999444c061aSmrg CheckExposureEvent, (char *) &info)) { 1000444c061aSmrg 1001444c061aSmrg count = GetCount(&event_return); 1002444c061aSmrg if (no_region) 1003444c061aSmrg AddExposureToRectangularRegion(&event_return, pd->region); 1004444c061aSmrg else 1005444c061aSmrg XtAddExposureToRegion(&event_return, pd->region); 1006444c061aSmrg } 1007444c061aSmrg else if (count != 0) { 1008444c061aSmrg XIfEvent(dpy, &event_return, 1009444c061aSmrg CheckExposureEvent, (char *) &info); 1010444c061aSmrg count = GetCount(&event_return); 1011444c061aSmrg if (no_region) 1012444c061aSmrg AddExposureToRectangularRegion(&event_return, pd->region); 1013444c061aSmrg else 1014444c061aSmrg XtAddExposureToRegion(&event_return, pd->region); 1015444c061aSmrg } 1016444c061aSmrg else /* count == 0 && XCheckIfEvent Failed. */ 1017444c061aSmrg break; 1018444c061aSmrg } 1019444c061aSmrg 1020444c061aSmrg SendExposureEvent(event, widget, pd); 1021444c061aSmrg} 1022444c061aSmrg 1023444c061aSmrgvoid XtAddExposureToRegion( 1024444c061aSmrg XEvent *event, 1025444c061aSmrg Region region) 1026444c061aSmrg{ 1027444c061aSmrg XRectangle rect; 1028444c061aSmrg XExposeEvent *ev = (XExposeEvent *) event; 1029444c061aSmrg /* These Expose and GraphicsExpose fields are at identical offsets */ 1030444c061aSmrg 1031444c061aSmrg if (event->type == Expose || event->type == GraphicsExpose) { 1032444c061aSmrg rect.x = ev->x; 1033444c061aSmrg rect.y = ev->y; 1034444c061aSmrg rect.width = ev->width; 1035444c061aSmrg rect.height = ev->height; 1036444c061aSmrg XUnionRectWithRegion(&rect, region, region); 1037444c061aSmrg } 1038444c061aSmrg} 1039444c061aSmrg 1040444c061aSmrg#ifndef MAX 1041444c061aSmrg#define MAX(a,b) (((a) > (b)) ? (a) : (b)) 1042444c061aSmrg#endif 1043444c061aSmrg 1044444c061aSmrg#ifndef MIN 1045444c061aSmrg#define MIN(a,b) (((a) < (b)) ? (a) : (b)) 1046444c061aSmrg#endif 1047444c061aSmrg 1048444c061aSmrgstatic void AddExposureToRectangularRegion( 1049444c061aSmrg XEvent *event, /* when called internally, type is always appropriate */ 1050444c061aSmrg Region region) 1051444c061aSmrg{ 1052444c061aSmrg XRectangle rect; 1053444c061aSmrg XExposeEvent *ev = (XExposeEvent *) event; 1054444c061aSmrg /* These Expose and GraphicsExpose fields are at identical offsets */ 1055444c061aSmrg 1056444c061aSmrg rect.x = ev->x; 1057444c061aSmrg rect.y = ev->y; 1058444c061aSmrg rect.width = ev->width; 1059444c061aSmrg rect.height = ev->height; 1060444c061aSmrg 1061444c061aSmrg if (XEmptyRegion(region)) { 1062444c061aSmrg XUnionRectWithRegion(&rect, region, region); 1063444c061aSmrg } else { 1064444c061aSmrg XRectangle merged, bbox; 1065444c061aSmrg 1066444c061aSmrg XClipBox(region, &bbox); 1067444c061aSmrg merged.x = MIN(rect.x, bbox.x); 1068444c061aSmrg merged.y = MIN(rect.y, bbox.y); 1069444c061aSmrg merged.width = MAX(rect.x + rect.width, 1070444c061aSmrg bbox.x + bbox.width) - merged.x; 1071444c061aSmrg merged.height = MAX(rect.y + rect.height, 1072444c061aSmrg bbox.y + bbox.height) - merged.y; 1073444c061aSmrg XUnionRectWithRegion(&merged, region, region); 1074444c061aSmrg } 1075444c061aSmrg} 1076444c061aSmrg 1077444c061aSmrgstatic Region nullRegion; 1078444c061aSmrg/* READ-ONLY VARIABLES: nullRegion */ 1079444c061aSmrg 1080444c061aSmrgvoid _XtEventInitialize(void) 1081444c061aSmrg{ 1082444c061aSmrg#ifndef __lock_lint 1083444c061aSmrg nullRegion = XCreateRegion(); 1084444c061aSmrg#endif 1085444c061aSmrg} 1086444c061aSmrg 1087444c061aSmrg/* Function Name: SendExposureEvent 1088444c061aSmrg * Description: Sets the x, y, width, and height of the event 1089444c061aSmrg * to be the clip box of Expose Region. 1090444c061aSmrg * Arguments: event - the X Event to mangle; Expose or GraphicsExpose. 1091444c061aSmrg * widget - the widget that this event occured in. 1092444c061aSmrg * pd - the per display information for this widget. 1093444c061aSmrg * Returns: none. 1094444c061aSmrg */ 1095444c061aSmrg 1096444c061aSmrgstatic void 1097444c061aSmrgSendExposureEvent( 1098444c061aSmrgXEvent * event, 1099444c061aSmrgWidget widget, 1100444c061aSmrgXtPerDisplay pd) 1101444c061aSmrg{ 1102444c061aSmrg XtExposeProc expose; 1103444c061aSmrg XRectangle rect; 1104444c061aSmrg XtEnum comp_expose; 1105444c061aSmrg XExposeEvent *ev = (XExposeEvent *) event; 1106444c061aSmrg 1107444c061aSmrg XClipBox(pd->region, &rect); 1108444c061aSmrg ev->x = rect.x; 1109444c061aSmrg ev->y = rect.y; 1110444c061aSmrg ev->width = rect.width; 1111444c061aSmrg ev->height = rect.height; 1112444c061aSmrg 1113444c061aSmrg LOCK_PROCESS; 1114444c061aSmrg comp_expose = COMP_EXPOSE; 1115444c061aSmrg expose = widget->core.widget_class->core_class.expose; 1116444c061aSmrg UNLOCK_PROCESS; 1117444c061aSmrg if (comp_expose & XtExposeNoRegion) 1118444c061aSmrg (*expose)(widget, event, NULL); 1119444c061aSmrg else 1120444c061aSmrg (*expose)(widget, event, pd->region); 1121444c061aSmrg (void) XIntersectRegion(nullRegion, pd->region, pd->region); 1122444c061aSmrg} 1123444c061aSmrg 1124444c061aSmrg/* Function Name: CheckExposureEvent 1125444c061aSmrg * Description: Checks the event queue for an expose event 1126444c061aSmrg * Arguments: display - the display connection. 1127444c061aSmrg * event - the event to check. 1128444c061aSmrg * arg - a pointer to the exposure info structure. 1129444c061aSmrg * Returns: TRUE if we found an event of the correct type 1130444c061aSmrg * with the right window. 1131444c061aSmrg * 1132444c061aSmrg * NOTE: The only valid types (info.type1 and info.type2) are Expose 1133444c061aSmrg * and GraphicsExpose. 1134444c061aSmrg */ 1135444c061aSmrg 1136444c061aSmrg/* ARGSUSED */ 1137444c061aSmrgstatic Bool 1138444c061aSmrgCheckExposureEvent( 1139444c061aSmrgDisplay * disp, 1140444c061aSmrgXEvent * event, 1141444c061aSmrgchar * arg) 1142444c061aSmrg{ 1143444c061aSmrg CheckExposeInfo * info = ((CheckExposeInfo *) arg); 1144444c061aSmrg 1145444c061aSmrg if ( (info->type1 == event->type) || (info->type2 == event->type)) { 1146444c061aSmrg if (!info->maximal && info->non_matching) return FALSE; 1147444c061aSmrg if (event->type == GraphicsExpose) 1148444c061aSmrg return(event->xgraphicsexpose.drawable == info->window); 1149444c061aSmrg return(event->xexpose.window == info->window); 1150444c061aSmrg } 1151444c061aSmrg info->non_matching = TRUE; 1152444c061aSmrg return(FALSE); 1153444c061aSmrg} 1154444c061aSmrg 1155444c061aSmrgstatic EventMask const masks[] = { 1156444c061aSmrg 0, /* Error, should never see */ 1157444c061aSmrg 0, /* Reply, should never see */ 1158444c061aSmrg KeyPressMask, /* KeyPress */ 1159444c061aSmrg KeyReleaseMask, /* KeyRelease */ 1160444c061aSmrg ButtonPressMask, /* ButtonPress */ 1161444c061aSmrg ButtonReleaseMask, /* ButtonRelease */ 1162444c061aSmrg PointerMotionMask /* MotionNotify */ 1163444c061aSmrg | ButtonMotionMask, 1164444c061aSmrg EnterWindowMask, /* EnterNotify */ 1165444c061aSmrg LeaveWindowMask, /* LeaveNotify */ 1166444c061aSmrg FocusChangeMask, /* FocusIn */ 1167444c061aSmrg FocusChangeMask, /* FocusOut */ 1168444c061aSmrg KeymapStateMask, /* KeymapNotify */ 1169444c061aSmrg ExposureMask, /* Expose */ 1170444c061aSmrg NonMaskableMask, /* GraphicsExpose, in GC */ 1171444c061aSmrg NonMaskableMask, /* NoExpose, in GC */ 1172444c061aSmrg VisibilityChangeMask, /* VisibilityNotify */ 1173444c061aSmrg SubstructureNotifyMask, /* CreateNotify */ 1174444c061aSmrg StructureNotifyMask /* DestroyNotify */ 1175444c061aSmrg | SubstructureNotifyMask, 1176444c061aSmrg StructureNotifyMask /* UnmapNotify */ 1177444c061aSmrg | SubstructureNotifyMask, 1178444c061aSmrg StructureNotifyMask /* MapNotify */ 1179444c061aSmrg | SubstructureNotifyMask, 1180444c061aSmrg SubstructureRedirectMask, /* MapRequest */ 1181444c061aSmrg StructureNotifyMask /* ReparentNotify */ 1182444c061aSmrg | SubstructureNotifyMask, 1183444c061aSmrg StructureNotifyMask /* ConfigureNotify */ 1184444c061aSmrg | SubstructureNotifyMask, 1185444c061aSmrg SubstructureRedirectMask, /* ConfigureRequest */ 1186444c061aSmrg StructureNotifyMask /* GravityNotify */ 1187444c061aSmrg | SubstructureNotifyMask, 1188444c061aSmrg ResizeRedirectMask, /* ResizeRequest */ 1189444c061aSmrg StructureNotifyMask /* CirculateNotify */ 1190444c061aSmrg | SubstructureNotifyMask, 1191444c061aSmrg SubstructureRedirectMask, /* CirculateRequest */ 1192444c061aSmrg PropertyChangeMask, /* PropertyNotify */ 1193444c061aSmrg NonMaskableMask, /* SelectionClear */ 1194444c061aSmrg NonMaskableMask, /* SelectionRequest */ 1195444c061aSmrg NonMaskableMask, /* SelectionNotify */ 1196444c061aSmrg ColormapChangeMask, /* ColormapNotify */ 1197444c061aSmrg NonMaskableMask, /* ClientMessage */ 1198444c061aSmrg NonMaskableMask /* MappingNotify */ 1199444c061aSmrg}; 1200444c061aSmrg 1201444c061aSmrgEventMask _XtConvertTypeToMask ( 1202444c061aSmrg int eventType) 1203444c061aSmrg{ 1204444c061aSmrg if ((Cardinal) eventType < XtNumber(masks)) 1205444c061aSmrg return masks[eventType]; 1206444c061aSmrg else 1207444c061aSmrg return NoEventMask; 1208444c061aSmrg} 1209444c061aSmrg 1210444c061aSmrgBoolean _XtOnGrabList( 1211444c061aSmrg register Widget widget, 1212444c061aSmrg XtGrabRec *grabList) 1213444c061aSmrg{ 1214444c061aSmrg register XtGrabRec* gl; 1215444c061aSmrg for (; widget != NULL; widget = (Widget)widget->core.parent) { 1216444c061aSmrg for (gl = grabList; gl != NULL; gl = gl->next) { 1217444c061aSmrg if (gl->widget == widget) return TRUE; 1218444c061aSmrg if (gl->exclusive) break; 1219444c061aSmrg } 1220444c061aSmrg } 1221444c061aSmrg return FALSE; 1222444c061aSmrg} 1223444c061aSmrg 1224444c061aSmrgstatic Widget LookupSpringLoaded( 1225444c061aSmrg XtGrabList grabList) 1226444c061aSmrg{ 1227444c061aSmrg XtGrabList gl; 1228444c061aSmrg 1229444c061aSmrg for (gl = grabList; gl != NULL; gl = gl->next) { 1230444c061aSmrg if (gl->spring_loaded) { 1231444c061aSmrg if (XtIsSensitive(gl->widget)) 1232444c061aSmrg return gl->widget; 1233444c061aSmrg else 1234444c061aSmrg return NULL; 1235444c061aSmrg } 1236444c061aSmrg if (gl->exclusive) break; 1237444c061aSmrg } 1238444c061aSmrg return NULL; 1239444c061aSmrg} 1240444c061aSmrg 1241444c061aSmrgstatic Boolean DispatchEvent( 1242444c061aSmrg XEvent* event, 1243444c061aSmrg Widget widget) 1244444c061aSmrg{ 1245444c061aSmrg 1246444c061aSmrg if (event->type == EnterNotify && 1247444c061aSmrg event->xcrossing.mode == NotifyNormal && 1248444c061aSmrg widget->core.widget_class->core_class.compress_enterleave) { 1249444c061aSmrg if (XPending(event->xcrossing.display)) { 1250444c061aSmrg XEvent nextEvent; 1251444c061aSmrg XPeekEvent(event->xcrossing.display, &nextEvent); 1252444c061aSmrg if (nextEvent.type == LeaveNotify && 1253444c061aSmrg event->xcrossing.window == nextEvent.xcrossing.window && 1254444c061aSmrg nextEvent.xcrossing.mode == NotifyNormal && 1255444c061aSmrg ((event->xcrossing.detail != NotifyInferior && 1256444c061aSmrg nextEvent.xcrossing.detail != NotifyInferior) || 1257444c061aSmrg (event->xcrossing.detail == NotifyInferior && 1258444c061aSmrg nextEvent.xcrossing.detail == NotifyInferior))) { 1259444c061aSmrg /* skip the enter/leave pair */ 1260444c061aSmrg XNextEvent(event->xcrossing.display, &nextEvent); 1261444c061aSmrg return False; 1262444c061aSmrg } 1263444c061aSmrg } 1264444c061aSmrg } 1265444c061aSmrg 1266444c061aSmrg if (event->type == MotionNotify && 1267444c061aSmrg widget->core.widget_class->core_class.compress_motion) { 1268444c061aSmrg while (XPending(event->xmotion.display)) { 1269444c061aSmrg XEvent nextEvent; 1270444c061aSmrg XPeekEvent(event->xmotion.display, &nextEvent); 1271444c061aSmrg if (nextEvent.type == MotionNotify && 1272444c061aSmrg event->xmotion.window == nextEvent.xmotion.window && 1273444c061aSmrg event->xmotion.subwindow == nextEvent.xmotion.subwindow) { 1274444c061aSmrg /* replace the current event with the next one */ 1275444c061aSmrg XNextEvent(event->xmotion.display, event); 1276444c061aSmrg } else break; 1277444c061aSmrg } 1278444c061aSmrg } 1279444c061aSmrg 1280444c061aSmrg return XtDispatchEventToWidget(widget, event); 1281444c061aSmrg} 1282444c061aSmrg 1283444c061aSmrgtypedef enum _GrabType {pass, ignore, remap} GrabType; 1284444c061aSmrg 1285444c061aSmrg#if !defined(AIXV3) || !defined(AIXSHLIB) 1286444c061aSmrgstatic /* AIX shared libraries are broken */ 1287444c061aSmrg#endif 1288444c061aSmrgBoolean _XtDefaultDispatcher( 1289444c061aSmrg XEvent *event) 1290444c061aSmrg{ 1291444c061aSmrg register Widget widget; 1292444c061aSmrg GrabType grabType; 1293444c061aSmrg XtPerDisplayInput pdi; 1294444c061aSmrg XtGrabList grabList; 1295444c061aSmrg Boolean was_dispatched = False; 1296444c061aSmrg DPY_TO_APPCON(event->xany.display); 1297444c061aSmrg 1298444c061aSmrg /* the default dispatcher discards all extension events */ 1299444c061aSmrg if (event->type >= LASTEvent) 1300444c061aSmrg return False; 1301444c061aSmrg 1302444c061aSmrg LOCK_APP(app); 1303444c061aSmrg 1304444c061aSmrg switch (event->type) { 1305444c061aSmrg case KeyPress: 1306444c061aSmrg case KeyRelease: 1307444c061aSmrg case ButtonPress: 1308444c061aSmrg case ButtonRelease: grabType = remap; break; 1309444c061aSmrg case MotionNotify: 1310444c061aSmrg case EnterNotify: grabType = ignore; break; 1311444c061aSmrg default: grabType = pass; break; 1312444c061aSmrg } 1313444c061aSmrg 1314444c061aSmrg widget = XtWindowToWidget (event->xany.display, event->xany.window); 1315444c061aSmrg pdi = _XtGetPerDisplayInput(event->xany.display); 1316444c061aSmrg grabList = *_XtGetGrabList(pdi); 1317444c061aSmrg 1318444c061aSmrg if (widget == NULL) { 1319444c061aSmrg if (grabType == remap 1320444c061aSmrg && (widget = LookupSpringLoaded(grabList)) != NULL) { 1321444c061aSmrg /* event occurred in a non-widget window, but we've promised also 1322444c061aSmrg to dispatch it to the nearest accessible spring_loaded widget */ 1323444c061aSmrg was_dispatched = (XFilterEvent(event, XtWindow(widget)) 1324444c061aSmrg || XtDispatchEventToWidget(widget, event)); 1325444c061aSmrg } 1326444c061aSmrg else was_dispatched = XFilterEvent(event, None); 1327444c061aSmrg } 1328444c061aSmrg else if (grabType == pass) { 1329444c061aSmrg if (event->type == LeaveNotify || 1330444c061aSmrg event->type == FocusIn || 1331444c061aSmrg event->type == FocusOut) { 1332444c061aSmrg if (XtIsSensitive (widget)) 1333444c061aSmrg was_dispatched = (XFilterEvent(event, XtWindow(widget)) || 1334444c061aSmrg XtDispatchEventToWidget(widget, event)); 1335444c061aSmrg } else was_dispatched = (XFilterEvent(event, XtWindow(widget)) || 1336444c061aSmrg XtDispatchEventToWidget(widget, event)); 1337444c061aSmrg } 1338444c061aSmrg else if (grabType == ignore) { 1339444c061aSmrg if ((grabList == NULL || _XtOnGrabList(widget, grabList)) 1340444c061aSmrg && XtIsSensitive(widget)) { 1341444c061aSmrg was_dispatched = (XFilterEvent(event, XtWindow(widget)) 1342444c061aSmrg || DispatchEvent(event, widget)); 1343444c061aSmrg } 1344444c061aSmrg } 1345444c061aSmrg else if (grabType == remap) { 1346444c061aSmrg EventMask mask = _XtConvertTypeToMask(event->type); 1347444c061aSmrg Widget dspWidget; 1348444c061aSmrg Boolean was_filtered = False; 1349444c061aSmrg 1350444c061aSmrg dspWidget = _XtFindRemapWidget(event, widget, mask, pdi); 1351444c061aSmrg 1352444c061aSmrg if ((grabList == NULL ||_XtOnGrabList(dspWidget, grabList)) 1353444c061aSmrg && XtIsSensitive(dspWidget)) { 1354444c061aSmrg if ((was_filtered = XFilterEvent(event, XtWindow(dspWidget)))) { 1355444c061aSmrg /* If this event activated a device grab, release it. */ 1356444c061aSmrg _XtUngrabBadGrabs(event, widget, mask, pdi); 1357444c061aSmrg was_dispatched = True; 1358444c061aSmrg } else 1359444c061aSmrg was_dispatched = XtDispatchEventToWidget(dspWidget, event); 1360444c061aSmrg } 1361444c061aSmrg else _XtUngrabBadGrabs(event, widget, mask, pdi); 1362444c061aSmrg 1363444c061aSmrg if (!was_filtered) { 1364444c061aSmrg /* Also dispatch to nearest accessible spring_loaded. */ 1365444c061aSmrg /* Fetch this afterward to reflect modal list changes */ 1366444c061aSmrg grabList = *_XtGetGrabList(pdi); 1367444c061aSmrg widget = LookupSpringLoaded(grabList); 1368444c061aSmrg if (widget != NULL && widget != dspWidget) { 1369444c061aSmrg was_dispatched = (XFilterEvent(event, XtWindow(widget)) 1370444c061aSmrg || XtDispatchEventToWidget(widget, event) 1371444c061aSmrg || was_dispatched); 1372444c061aSmrg } 1373444c061aSmrg } 1374444c061aSmrg } 1375444c061aSmrg UNLOCK_APP(app); 1376444c061aSmrg return was_dispatched; 1377444c061aSmrg} 1378444c061aSmrg 1379444c061aSmrgBoolean XtDispatchEvent ( 1380444c061aSmrg XEvent *event) 1381444c061aSmrg{ 1382444c061aSmrg Boolean was_dispatched, safe; 1383444c061aSmrg int dispatch_level; 1384444c061aSmrg int starting_count; 1385444c061aSmrg XtPerDisplay pd; 1386444c061aSmrg Time time = 0; 1387444c061aSmrg XtEventDispatchProc dispatch = _XtDefaultDispatcher; 1388444c061aSmrg XtAppContext app = XtDisplayToApplicationContext(event->xany.display); 1389444c061aSmrg 1390444c061aSmrg LOCK_APP(app); 1391444c061aSmrg dispatch_level = ++app->dispatch_level; 1392444c061aSmrg starting_count = app->destroy_count; 1393444c061aSmrg 1394444c061aSmrg switch (event->type) { 1395444c061aSmrg case KeyPress: 1396444c061aSmrg case KeyRelease: time = event->xkey.time; break; 1397444c061aSmrg case ButtonPress: 1398444c061aSmrg case ButtonRelease: time = event->xbutton.time; break; 1399444c061aSmrg case MotionNotify: time = event->xmotion.time; break; 1400444c061aSmrg case EnterNotify: 1401444c061aSmrg case LeaveNotify: time = event->xcrossing.time; break; 1402444c061aSmrg case PropertyNotify: time = event->xproperty.time; break; 1403444c061aSmrg case SelectionClear: time = event->xselectionclear.time; break; 1404444c061aSmrg 1405444c061aSmrg case MappingNotify: _XtRefreshMapping(event, True); break; 1406444c061aSmrg } 1407444c061aSmrg pd = _XtGetPerDisplay(event->xany.display); 1408444c061aSmrg if (time) pd->last_timestamp = time; 1409444c061aSmrg pd->last_event = *event; 1410444c061aSmrg 1411444c061aSmrg if (pd->dispatcher_list) { 1412444c061aSmrg dispatch = pd->dispatcher_list[event->type]; 1413444c061aSmrg if (dispatch == NULL) dispatch = _XtDefaultDispatcher; 1414444c061aSmrg } 1415444c061aSmrg was_dispatched = (*dispatch)(event); 1416444c061aSmrg 1417444c061aSmrg /* 1418444c061aSmrg * To make recursive XtDispatchEvent work, we need to do phase 2 destroys 1419444c061aSmrg * only on those widgets destroyed by this particular dispatch. 1420444c061aSmrg * 1421444c061aSmrg */ 1422444c061aSmrg 1423444c061aSmrg if (app->destroy_count > starting_count) 1424444c061aSmrg _XtDoPhase2Destroy(app, dispatch_level); 1425444c061aSmrg 1426444c061aSmrg app->dispatch_level = dispatch_level - 1; 1427444c061aSmrg 1428444c061aSmrg if ((safe = _XtSafeToDestroy(app))) { 1429444c061aSmrg if (app->dpy_destroy_count != 0) _XtCloseDisplays(app); 1430444c061aSmrg if (app->free_bindings) _XtDoFreeBindings(app); 1431444c061aSmrg } 1432444c061aSmrg UNLOCK_APP(app); 1433444c061aSmrg LOCK_PROCESS; 1434444c061aSmrg if (_XtAppDestroyCount != 0 && safe) _XtDestroyAppContexts(); 1435444c061aSmrg UNLOCK_PROCESS; 1436444c061aSmrg return was_dispatched; 1437444c061aSmrg} 1438444c061aSmrg 1439444c061aSmrg/* ARGSUSED */ 1440444c061aSmrgstatic void GrabDestroyCallback( 1441444c061aSmrg Widget widget, 1442444c061aSmrg XtPointer closure, 1443444c061aSmrg XtPointer call_data) 1444444c061aSmrg{ 1445444c061aSmrg /* Remove widget from grab list if it destroyed */ 1446444c061aSmrg XtRemoveGrab(widget); 1447444c061aSmrg} 1448444c061aSmrg 1449444c061aSmrgstatic XtGrabRec *NewGrabRec( 1450444c061aSmrg Widget widget, 1451444c061aSmrg Boolean exclusive, 1452444c061aSmrg Boolean spring_loaded) 1453444c061aSmrg{ 1454444c061aSmrg register XtGrabList gl; 1455444c061aSmrg 1456444c061aSmrg gl = XtNew(XtGrabRec); 1457444c061aSmrg gl->next = NULL; 1458444c061aSmrg gl->widget = widget; 1459444c061aSmrg gl->exclusive = exclusive; 1460444c061aSmrg gl->spring_loaded = spring_loaded; 1461444c061aSmrg 1462444c061aSmrg return gl; 1463444c061aSmrg} 1464444c061aSmrg 1465444c061aSmrgvoid XtAddGrab( 1466444c061aSmrg Widget widget, 1467444c061aSmrg _XtBoolean exclusive, 1468444c061aSmrg _XtBoolean spring_loaded) 1469444c061aSmrg{ 1470444c061aSmrg register XtGrabList gl; 1471444c061aSmrg XtGrabList *grabListPtr; 1472444c061aSmrg XtAppContext app = XtWidgetToApplicationContext(widget); 1473444c061aSmrg 1474444c061aSmrg LOCK_APP(app); 1475444c061aSmrg LOCK_PROCESS; 1476444c061aSmrg grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget))); 1477444c061aSmrg 1478444c061aSmrg if (spring_loaded && !exclusive) { 1479444c061aSmrg XtAppWarningMsg(app, 1480444c061aSmrg "grabError", "xtAddGrab", XtCXtToolkitError, 1481444c061aSmrg "XtAddGrab requires exclusive grab if spring_loaded is TRUE", 1482444c061aSmrg (String *) NULL, (Cardinal *) NULL); 1483444c061aSmrg exclusive = TRUE; 1484444c061aSmrg } 1485444c061aSmrg 1486444c061aSmrg gl = NewGrabRec(widget, exclusive, spring_loaded); 1487444c061aSmrg gl->next = *grabListPtr; 1488444c061aSmrg *grabListPtr = gl; 1489444c061aSmrg 1490444c061aSmrg XtAddCallback (widget, XtNdestroyCallback, 1491444c061aSmrg GrabDestroyCallback, (XtPointer) NULL); 1492444c061aSmrg UNLOCK_PROCESS; 1493444c061aSmrg UNLOCK_APP(app); 1494444c061aSmrg} 1495444c061aSmrg 1496444c061aSmrgvoid XtRemoveGrab( 1497444c061aSmrg Widget widget) 1498444c061aSmrg{ 1499444c061aSmrg register XtGrabList gl; 1500444c061aSmrg register Boolean done; 1501444c061aSmrg XtGrabList *grabListPtr; 1502444c061aSmrg XtAppContext app = XtWidgetToApplicationContext(widget); 1503444c061aSmrg 1504444c061aSmrg LOCK_APP(app); 1505444c061aSmrg LOCK_PROCESS; 1506444c061aSmrg 1507444c061aSmrg grabListPtr = _XtGetGrabList(_XtGetPerDisplayInput(XtDisplay(widget))); 1508444c061aSmrg 1509444c061aSmrg for (gl = *grabListPtr; gl != NULL; gl = gl->next) { 1510444c061aSmrg if (gl->widget == widget) break; 1511444c061aSmrg } 1512444c061aSmrg 1513444c061aSmrg if (gl == NULL) { 1514444c061aSmrg XtAppWarningMsg(app, 1515444c061aSmrg "grabError","xtRemoveGrab",XtCXtToolkitError, 1516444c061aSmrg "XtRemoveGrab asked to remove a widget not on the list", 1517444c061aSmrg (String *)NULL, (Cardinal *)NULL); 1518444c061aSmrg UNLOCK_PROCESS; 1519444c061aSmrg UNLOCK_APP(app); 1520444c061aSmrg return; 1521444c061aSmrg } 1522444c061aSmrg 1523444c061aSmrg do { 1524444c061aSmrg gl = *grabListPtr; 1525444c061aSmrg done = (gl->widget == widget); 1526444c061aSmrg *grabListPtr = gl->next; 1527444c061aSmrg XtRemoveCallback(gl->widget, XtNdestroyCallback, 1528444c061aSmrg GrabDestroyCallback, (XtPointer)NULL); 1529444c061aSmrg XtFree((char *)gl); 1530444c061aSmrg } while (! done); 1531444c061aSmrg UNLOCK_PROCESS; 1532444c061aSmrg UNLOCK_APP(app); 1533444c061aSmrg return; 1534444c061aSmrg} 1535444c061aSmrg 1536444c061aSmrgvoid XtMainLoop(void) 1537444c061aSmrg{ 1538444c061aSmrg XtAppMainLoop(_XtDefaultAppContext()); 1539444c061aSmrg} 1540444c061aSmrg 1541444c061aSmrgvoid XtAppMainLoop( 1542444c061aSmrg XtAppContext app) 1543444c061aSmrg{ 1544444c061aSmrg XEvent event; 1545444c061aSmrg 1546444c061aSmrg LOCK_APP(app); 1547444c061aSmrg do { 1548444c061aSmrg XtAppNextEvent(app, &event); 1549444c061aSmrg#ifdef XTHREADS 1550444c061aSmrg /* assert(app == XtDisplayToApplicationContext(event.xany.display)); */ 1551444c061aSmrg#endif 1552444c061aSmrg XtDispatchEvent(&event); 1553444c061aSmrg } while(app->exit_flag == FALSE); 1554444c061aSmrg UNLOCK_APP(app); 1555444c061aSmrg} 1556444c061aSmrg 1557444c061aSmrgvoid _XtFreeEventTable( 1558444c061aSmrg XtEventTable *event_table) 1559444c061aSmrg{ 1560444c061aSmrg register XtEventTable event; 1561444c061aSmrg 1562444c061aSmrg event = *event_table; 1563444c061aSmrg while (event != NULL) { 1564444c061aSmrg register XtEventTable next = event->next; 1565444c061aSmrg XtFree((char *) event); 1566444c061aSmrg event = next; 1567444c061aSmrg } 1568444c061aSmrg} 1569444c061aSmrg 1570444c061aSmrgTime XtLastTimestampProcessed( 1571444c061aSmrg Display *dpy) 1572444c061aSmrg{ 1573444c061aSmrg Time time; 1574444c061aSmrg DPY_TO_APPCON(dpy); 1575444c061aSmrg 1576444c061aSmrg LOCK_APP(app); 1577444c061aSmrg LOCK_PROCESS; 1578444c061aSmrg time = _XtGetPerDisplay(dpy)->last_timestamp; 1579444c061aSmrg UNLOCK_PROCESS; 1580444c061aSmrg UNLOCK_APP(app); 1581444c061aSmrg return(time); 1582444c061aSmrg} 1583444c061aSmrg 1584444c061aSmrgXEvent* XtLastEventProcessed( 1585444c061aSmrg Display* dpy) 1586444c061aSmrg{ 1587444c061aSmrg XEvent* le = NULL; 1588444c061aSmrg DPY_TO_APPCON(dpy); 1589444c061aSmrg 1590444c061aSmrg LOCK_APP(app); 1591444c061aSmrg le = &_XtGetPerDisplay(dpy)->last_event; 1592444c061aSmrg if (!le->xany.serial) 1593444c061aSmrg le = NULL; 1594444c061aSmrg UNLOCK_APP(app); 1595444c061aSmrg return le; 1596444c061aSmrg} 1597444c061aSmrg 1598444c061aSmrgvoid _XtSendFocusEvent( 1599444c061aSmrg Widget child, 1600444c061aSmrg int type) 1601444c061aSmrg{ 1602444c061aSmrg child = XtIsWidget(child) ? child : _XtWindowedAncestor(child); 1603444c061aSmrg if (XtIsSensitive(child) && !child->core.being_destroyed 1604444c061aSmrg && XtIsRealized(child) 1605444c061aSmrg && (XtBuildEventMask(child) & FocusChangeMask)) 1606444c061aSmrg { 1607444c061aSmrg XFocusChangeEvent event; 1608444c061aSmrg Display* dpy = XtDisplay (child); 1609444c061aSmrg 1610444c061aSmrg event.type = type; 1611444c061aSmrg event.serial = LastKnownRequestProcessed(dpy); 1612444c061aSmrg event.send_event = True; 1613444c061aSmrg event.display = dpy; 1614444c061aSmrg event.window = XtWindow(child); 1615444c061aSmrg event.mode = NotifyNormal; 1616444c061aSmrg event.detail = NotifyAncestor; 1617444c061aSmrg if (XFilterEvent((XEvent*)&event, XtWindow(child))) 1618444c061aSmrg return; 1619444c061aSmrg XtDispatchEventToWidget(child, (XEvent*)&event); 1620444c061aSmrg } 1621444c061aSmrg} 1622444c061aSmrg 1623444c061aSmrgstatic XtEventDispatchProc* NewDispatcherList(void) 1624444c061aSmrg{ 1625444c061aSmrg XtEventDispatchProc* l = 1626444c061aSmrg (XtEventDispatchProc*) __XtCalloc((Cardinal) 128, 1627444c061aSmrg (Cardinal)sizeof(XtEventDispatchProc)); 1628444c061aSmrg return l; 1629444c061aSmrg} 1630444c061aSmrg 1631444c061aSmrgXtEventDispatchProc XtSetEventDispatcher( 1632444c061aSmrg Display *dpy, 1633444c061aSmrg int event_type, 1634444c061aSmrg XtEventDispatchProc proc) 1635444c061aSmrg{ 1636444c061aSmrg XtEventDispatchProc *list; 1637444c061aSmrg XtEventDispatchProc old_proc; 1638444c061aSmrg register XtPerDisplay pd; 1639444c061aSmrg DPY_TO_APPCON(dpy); 1640444c061aSmrg 1641444c061aSmrg LOCK_APP(app); 1642444c061aSmrg LOCK_PROCESS; 1643444c061aSmrg pd = _XtGetPerDisplay(dpy); 1644444c061aSmrg 1645444c061aSmrg list = pd->dispatcher_list; 1646444c061aSmrg if (!list) { 1647444c061aSmrg if (proc) list = pd->dispatcher_list = NewDispatcherList(); 1648444c061aSmrg else return _XtDefaultDispatcher; 1649444c061aSmrg } 1650444c061aSmrg old_proc = list[event_type]; 1651444c061aSmrg list[event_type] = proc; 1652444c061aSmrg if (old_proc == NULL) old_proc = _XtDefaultDispatcher; 1653444c061aSmrg UNLOCK_PROCESS; 1654444c061aSmrg UNLOCK_APP(app); 1655444c061aSmrg return old_proc; 1656444c061aSmrg} 1657444c061aSmrg 1658444c061aSmrgvoid XtRegisterExtensionSelector( 1659444c061aSmrg Display *dpy, 1660444c061aSmrg int min_event_type, 1661444c061aSmrg int max_event_type, 1662444c061aSmrg XtExtensionSelectProc proc, 1663444c061aSmrg XtPointer client_data) 1664444c061aSmrg{ 1665444c061aSmrg ExtSelectRec *e; 1666444c061aSmrg XtPerDisplay pd; 1667444c061aSmrg int i; 1668444c061aSmrg DPY_TO_APPCON(dpy); 1669444c061aSmrg 1670444c061aSmrg if (dpy == NULL) XtErrorMsg("nullDisplay", 1671444c061aSmrg "xtRegisterExtensionSelector", XtCXtToolkitError, 1672444c061aSmrg "XtRegisterExtensionSelector requires a non-NULL display", 1673444c061aSmrg (String *) NULL, (Cardinal *) NULL); 1674444c061aSmrg 1675444c061aSmrg LOCK_APP(app); 1676444c061aSmrg LOCK_PROCESS; 1677444c061aSmrg pd = _XtGetPerDisplay(dpy); 1678444c061aSmrg 1679444c061aSmrg for (i = 0; i < pd->ext_select_count; i++) { 1680444c061aSmrg e = &pd->ext_select_list[i]; 1681444c061aSmrg if (e->min == min_event_type && e->max == max_event_type) { 1682444c061aSmrg e->proc = proc; 1683444c061aSmrg e->client_data = client_data; 1684444c061aSmrg return; 1685444c061aSmrg } 1686444c061aSmrg if ((min_event_type >= e->min && min_event_type <= e->max) || 1687444c061aSmrg (max_event_type >= e->min && max_event_type <= e->max)) { 1688444c061aSmrg XtErrorMsg("rangeError", "xtRegisterExtensionSelector", 1689444c061aSmrg XtCXtToolkitError, 1690444c061aSmrg "Attempt to register multiple selectors for one extension event type", 1691444c061aSmrg (String *) NULL, (Cardinal *) NULL); 1692444c061aSmrg UNLOCK_PROCESS; 1693444c061aSmrg UNLOCK_APP(app); 1694444c061aSmrg return; 1695444c061aSmrg } 1696444c061aSmrg } 1697444c061aSmrg pd->ext_select_count++; 1698444c061aSmrg pd->ext_select_list = 1699444c061aSmrg (ExtSelectRec *) XtRealloc((char *) pd->ext_select_list, 1700444c061aSmrg pd->ext_select_count * sizeof(ExtSelectRec)); 1701444c061aSmrg for (i = pd->ext_select_count - 1; i > 0; i--) { 1702444c061aSmrg if (pd->ext_select_list[i-1].min > min_event_type) { 1703444c061aSmrg pd->ext_select_list[i] = pd->ext_select_list[i-1]; 1704444c061aSmrg } else break; 1705444c061aSmrg } 1706444c061aSmrg pd->ext_select_list[i].min = min_event_type; 1707444c061aSmrg pd->ext_select_list[i].max = max_event_type; 1708444c061aSmrg pd->ext_select_list[i].proc = proc; 1709444c061aSmrg pd->ext_select_list[i].client_data = client_data; 1710444c061aSmrg UNLOCK_PROCESS; 1711444c061aSmrg UNLOCK_APP(app); 1712444c061aSmrg} 1713444c061aSmrg 1714444c061aSmrgvoid _XtExtensionSelect( 1715444c061aSmrg Widget widget) 1716444c061aSmrg{ 1717444c061aSmrg int i; 1718444c061aSmrg XtPerDisplay pd; 1719444c061aSmrg WIDGET_TO_APPCON(widget); 1720444c061aSmrg 1721444c061aSmrg LOCK_APP(app); 1722444c061aSmrg LOCK_PROCESS; 1723444c061aSmrg 1724444c061aSmrg pd = _XtGetPerDisplay(XtDisplay(widget)); 1725444c061aSmrg 1726444c061aSmrg for (i = 0; i < pd->ext_select_count; i++) { 1727444c061aSmrg CallExtensionSelector(widget, pd->ext_select_list+i, FALSE); 1728444c061aSmrg } 1729444c061aSmrg UNLOCK_PROCESS; 1730444c061aSmrg UNLOCK_APP(app); 1731444c061aSmrg} 1732