1/* 2 * tkMacOSXCarbonEvents.c -- 3 * 4 * This file implements functions that register for and handle 5 * various Carbon Events and Timers. Most carbon events of interest 6 * to TkAqua are processed in a handler registered on the dispatcher 7 * event target so that we get first crack at them before HIToolbox 8 * dispatchers/processes them further. 9 * As some events are sent directly to the focus or app event target 10 * and not dispatched normally, we also register a handler on the 11 * application event target. 12 * 13 * Copyright 2001, Apple Computer, Inc. 14 * Copyright (c) 2005-2008 Daniel A. Steffen <das@users.sourceforge.net> 15 * 16 * See the file "license.terms" for information on usage and redistribution of 17 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 18 * 19 * The following terms apply to all files originating from Apple 20 * Computer, Inc. ("Apple") and associated with the software 21 * unless explicitly disclaimed in individual files. 22 * 23 * 24 * Apple hereby grants permission to use, copy, modify, 25 * distribute, and license this software and its documentation 26 * for any purpose, provided that existing copyright notices are 27 * retained in all copies and that this notice is included 28 * verbatim in any distributions. No written agreement, license, 29 * or royalty fee is required for any of the authorized 30 * uses. Modifications to this software may be copyrighted by 31 * their authors and need not follow the licensing terms 32 * described here, provided that the new terms are clearly 33 * indicated on the first page of each file where they apply. 34 * 35 * 36 * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE 37 * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 38 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF 39 * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, 40 * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND 42 * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, 43 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 44 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS 45 * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE 46 * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE 47 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 48 * 49 * GOVERNMENT USE: If you are acquiring this software on behalf 50 * of the U.S. government, the Government shall have only 51 * "Restricted Rights" in the software and related documentation 52 * as defined in the Federal Acquisition Regulations (FARs) in 53 * Clause 52.227.19 (c) (2). If you are acquiring the software 54 * on behalf of the Department of Defense, the software shall be 55 * classified as "Commercial Computer Software" and the 56 * Government shall have only "Restricted Rights" as defined in 57 * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the 58 * foregoing, the authors grant the U.S. Government and others 59 * acting in its behalf permission to use and distribute the 60 * software in accordance with the terms specified in this 61 * license. 62 * 63 * RCS: @(#) $Id: tkMacOSXCarbonEvents.c,v 1.3.2.18 2007/11/09 06:26:54 das Exp $ 64 */ 65 66#include "tkMacOSXPrivate.h" 67#include "tkMacOSXEvent.h" 68#include "tkMacOSXDebug.h" 69 70/* 71#ifdef TK_MAC_DEBUG 72#define TK_MAC_DEBUG_CARBON_EVENTS 73#endif 74*/ 75 76/* 77 * Declarations of functions used only in this file: 78 */ 79 80static OSStatus CarbonEventHandlerProc(EventHandlerCallRef callRef, 81 EventRef event, void *userData); 82static OSStatus InstallStandardApplicationEventHandler(void); 83static void CarbonTimerProc(EventLoopTimerRef timer, void *userData); 84 85/* 86 * Static data used by several functions in this file: 87 */ 88 89static EventLoopTimerRef carbonTimer = NULL; 90static int carbonTimerEnabled = 0; 91static EventHandlerUPP carbonEventHandlerUPP = NULL; 92static Tcl_Interp *carbonEventInterp = NULL; 93static int inTrackingLoop = 0; 94 95#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 96/* 97 * For InstallStandardApplicationEventHandler(): 98 */ 99 100static jmp_buf exitRaelJmpBuf; 101static void ExitRaelEventHandlerProc(EventHandlerCallRef callRef, 102 EventRef event, void *userData) __attribute__ ((__noreturn__)); 103#endif 104 105 106/* 107 *---------------------------------------------------------------------- 108 * 109 * CarbonEventHandlerProc -- 110 * 111 * This procedure is the handler for all registered CarbonEvents. 112 * 113 * Results: 114 * OS status code. 115 * 116 * Side effects: 117 * Dispatches CarbonEvents. 118 * 119 *---------------------------------------------------------------------- 120 */ 121 122static OSStatus 123CarbonEventHandlerProc( 124 EventHandlerCallRef callRef, 125 EventRef event, 126 void *userData) 127{ 128 OSStatus err = eventNotHandledErr; 129 TkMacOSXEvent macEvent; 130 MacEventStatus eventStatus; 131 132 macEvent.eventRef = event; 133 macEvent.eClass = GetEventClass(event); 134 macEvent.eKind = GetEventKind(event); 135 macEvent.interp = (Tcl_Interp *) userData; 136 macEvent.callRef = callRef; 137 bzero(&eventStatus, sizeof(eventStatus)); 138 139#ifdef TK_MAC_DEBUG_CARBON_EVENTS 140 if (!(macEvent.eClass == kEventClassMouse && ( 141 macEvent.eKind == kEventMouseMoved || 142 macEvent.eKind == kEventMouseDragged))) { 143 TkMacOSXDbgMsg("Started handling %s", 144 TkMacOSXCarbonEventToAscii(event)); 145 TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, 146 EventRef inEvent); 147 if (_DebugPrintEvent) { 148 /* 149 * Carbon-internal event debugging (c.f. Technote 2124) 150 */ 151 152 _DebugPrintEvent(event); 153 } 154 } 155#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 156 157 TkMacOSXProcessEvent(&macEvent,&eventStatus); 158 if (eventStatus.stopProcessing) { 159 err = noErr; 160 } 161 162#ifdef TK_MAC_DEBUG_CARBON_EVENTS 163 if (macEvent.eKind != kEventMouseMoved && 164 macEvent.eKind != kEventMouseDragged) { 165 TkMacOSXDbgMsg("Finished handling %s: %s handled", 166 TkMacOSXCarbonEventToAscii(event), 167 eventStatus.stopProcessing ? " " : "not"); 168 } 169#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 170 return err; 171} 172 173/* 174 *---------------------------------------------------------------------- 175 * 176 * TkMacOSXInitCarbonEvents -- 177 * 178 * This procedure initializes all CarbonEvent handlers. 179 * 180 * Results: 181 * None. 182 * 183 * Side effects: 184 * Handlers for Carbon Events are registered. 185 * 186 *---------------------------------------------------------------------- 187 */ 188 189MODULE_SCOPE void 190TkMacOSXInitCarbonEvents( 191 Tcl_Interp *interp) 192{ 193 const EventTypeSpec dispatcherEventTypes[] = { 194 {kEventClassKeyboard, kEventRawKeyDown}, 195 {kEventClassKeyboard, kEventRawKeyRepeat}, 196 {kEventClassKeyboard, kEventRawKeyUp}, 197 {kEventClassKeyboard, kEventRawKeyModifiersChanged}, 198 {kEventClassKeyboard, kEventRawKeyRepeat}, 199 }; 200 const EventTypeSpec applicationEventTypes[] = { 201 {kEventClassMenu, kEventMenuBeginTracking}, 202 {kEventClassMenu, kEventMenuEndTracking}, 203 {kEventClassMenu, kEventMenuOpening}, 204 {kEventClassMenu, kEventMenuTargetItem}, 205 {kEventClassCommand, kEventCommandProcess}, 206 {kEventClassCommand, kEventCommandUpdateStatus}, 207 {kEventClassApplication, kEventAppActivated}, 208 {kEventClassApplication, kEventAppDeactivated}, 209 {kEventClassApplication, kEventAppQuit}, 210 {kEventClassApplication, kEventAppHidden}, 211 {kEventClassApplication, kEventAppShown}, 212 {kEventClassApplication, kEventAppAvailableWindowBoundsChanged}, 213 {kEventClassAppearance, kEventAppearanceScrollBarVariantChanged}, 214 }; 215 216 carbonEventHandlerUPP = NewEventHandlerUPP(CarbonEventHandlerProc); 217 carbonEventInterp = interp; 218 ChkErr(InstallStandardApplicationEventHandler); 219 ChkErr(InstallEventHandler, GetEventDispatcherTarget(), 220 carbonEventHandlerUPP, GetEventTypeCount(dispatcherEventTypes), 221 dispatcherEventTypes, (void *) carbonEventInterp, NULL); 222 ChkErr(InstallEventHandler, GetApplicationEventTarget(), 223 carbonEventHandlerUPP, GetEventTypeCount(applicationEventTypes), 224 applicationEventTypes, (void *) carbonEventInterp, NULL); 225 226#ifdef TK_MAC_DEBUG_CARBON_EVENTS 227 TkMacOSXInitNamedSymbol(HIToolbox, void, DebugTraceEvent, OSType, UInt32, 228 Boolean); 229 if (DebugTraceEvent) { 230 unsigned int i; 231 const EventTypeSpec *e; 232 233 for (i = 0, e = dispatcherEventTypes; 234 i < GetEventTypeCount(dispatcherEventTypes); i++, e++) { 235 DebugTraceEvent(e->eventClass, e->eventKind, 1); 236 } 237 for (i = 0, e = applicationEventTypes; 238 i < GetEventTypeCount(applicationEventTypes); i++, e++) { 239 DebugTraceEvent(e->eventClass, e->eventKind, 1); 240 } 241 DebugTraceEvent = NULL; /* Only enable tracing once. */ 242 } 243#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 244} 245 246/* 247 *---------------------------------------------------------------------- 248 * 249 * TkMacOSXInstallWindowCarbonEventHandler -- 250 * 251 * This procedure installs our window CarbonEvent handler. 252 * 253 * Results: 254 * None. 255 * 256 * Side effects: 257 * Handler for Carbon Events is registered. 258 * 259 *---------------------------------------------------------------------- 260 */ 261 262MODULE_SCOPE void 263TkMacOSXInstallWindowCarbonEventHandler( 264 Tcl_Interp *interp, WindowRef window) 265{ 266 const EventTypeSpec windowEventTypes[] = { 267 {kEventClassMouse, kEventMouseDown}, 268 {kEventClassMouse, kEventMouseUp}, 269 {kEventClassMouse, kEventMouseMoved}, 270 {kEventClassMouse, kEventMouseDragged}, 271 {kEventClassMouse, kEventMouseWheelMoved}, 272 {kEventClassWindow, kEventWindowActivated}, 273 {kEventClassWindow, kEventWindowDeactivated}, 274 {kEventClassWindow, kEventWindowUpdate}, 275 {kEventClassWindow, kEventWindowExpanding}, 276 {kEventClassWindow, kEventWindowBoundsChanged}, 277 {kEventClassWindow, kEventWindowDragStarted}, 278 {kEventClassWindow, kEventWindowDragCompleted}, 279 {kEventClassWindow, kEventWindowConstrain}, 280 {kEventClassWindow, kEventWindowGetRegion}, 281 {kEventClassWindow, kEventWindowDrawContent}, 282 }; 283 284 ChkErr(InstallEventHandler, GetWindowEventTarget(window), 285 carbonEventHandlerUPP, GetEventTypeCount(windowEventTypes), 286 windowEventTypes, (void *) (interp ? interp : carbonEventInterp), 287 NULL); 288 289#ifdef TK_MAC_DEBUG_CARBON_EVENTS 290 TkMacOSXInitNamedSymbol(HIToolbox, void, DebugTraceEvent, OSType, UInt32, 291 Boolean); 292 if (DebugTraceEvent) { 293 unsigned int i; 294 const EventTypeSpec *e; 295 296 for (i = 0, e = windowEventTypes; 297 i < GetEventTypeCount(windowEventTypes); i++, e++) { 298 if (!(e->eventClass == kEventClassMouse && ( 299 e->eventKind == kEventMouseMoved || 300 e->eventKind == kEventMouseDragged))) { 301 DebugTraceEvent(e->eventClass, e->eventKind, 1); 302 } 303 } 304 } 305#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 306} 307 308/* 309 *---------------------------------------------------------------------- 310 * 311 * InstallStandardApplicationEventHandler -- 312 * 313 * This procedure installs the carbon standard application event 314 * handler. 315 * 316 * Results: 317 * OS status code. 318 * 319 * Side effects: 320 * Standard handlers for application Carbon Events are registered. 321 * 322 *---------------------------------------------------------------------- 323 */ 324 325static OSStatus 326InstallStandardApplicationEventHandler(void) 327{ 328 OSStatus err = memFullErr; 329 330 TK_IF_HI_TOOLBOX(5, 331 /* 332 * The approach below does not work correctly in Leopard, it leads to 333 * crashes in [NSView unlockFocus] whenever HIToolbox uses Cocoa (Help 334 * menu, Nav Services, Color Picker). While it is now possible to 335 * install the standard app handler with InstallStandardEventHandler(), 336 * to fully replicate RAEL the standard menubar event handler also needs 337 * to be installed. Unfortunately there appears to be no public API to 338 * obtain the menubar event target. As a workaround, for now we resort 339 * to calling the HIToolbox-internal GetMenuBarEventTarget() directly 340 * (symbol acquired via TkMacOSXInitNamedSymbol() from HIToolbox 341 * version 343, may not exist in later versions). 342 */ 343 err = ChkErr(InstallStandardEventHandler, GetApplicationEventTarget()); 344 TkMacOSXInitNamedSymbol(HIToolbox, EventTargetRef, 345 GetMenuBarEventTarget, void); 346 if (GetMenuBarEventTarget) { 347 ChkErr(InstallStandardEventHandler, GetMenuBarEventTarget()); 348 } else { 349 TkMacOSXDbgMsg("Unable to install standard menubar event handler"); 350 } 351 ) TK_ELSE_HI_TOOLBOX (5, 352 /* 353 * This is a hack to workaround missing Carbon API to install the 354 * standard application event handler (InstallStandardEventHandler() 355 * does not work on the application target). The only way to install the 356 * standard app handler is to call RunApplicationEventLoop(), but since 357 * we are running our own event loop, we'll immediately need to break 358 * out of RAEL again: we do this via longjmp out of the 359 * ExitRaelEventHandlerProc event handler called first off from RAEL by 360 * posting a high priority dummy event. This workaround is derived from 361 * a similar approach in Technical Q&A 1061. 362 */ 363 enum { 364 kExitRaelEvent = 'ExiT' 365 }; 366 const EventTypeSpec exitRaelEventType = { 367 kExitRaelEvent, kExitRaelEvent 368 }; 369 EventHandlerUPP exitRaelEventHandler; 370 EventHandlerRef exitRaelEventHandlerRef = NULL; 371 EventRef exitRaelEvent = NULL; 372 373 exitRaelEventHandler = NewEventHandlerUPP( 374 (EventHandlerProcPtr) ExitRaelEventHandlerProc); 375 if (exitRaelEventHandler) { 376 err = ChkErr(InstallEventHandler, GetEventDispatcherTarget(), 377 exitRaelEventHandler, 1, &exitRaelEventType, NULL, 378 &exitRaelEventHandlerRef); 379 } 380 if (err == noErr) { 381 err = ChkErr(CreateEvent, NULL, kExitRaelEvent, kExitRaelEvent, 382 GetCurrentEventTime(), kEventAttributeNone, 383 &exitRaelEvent); 384 } 385 if (err == noErr) { 386 err = ChkErr(PostEventToQueue, GetMainEventQueue(), exitRaelEvent, 387 kEventPriorityHigh); 388 } 389 if (err == noErr) { 390 if (!setjmp(exitRaelJmpBuf)) { 391 RunApplicationEventLoop(); 392 393 /* 394 * This point should never be reached! 395 */ 396 397 Tcl_Panic("RunApplicationEventLoop exited !"); 398 } 399 } 400 if (exitRaelEvent) { 401 ReleaseEvent(exitRaelEvent); 402 } 403 if (exitRaelEventHandlerRef) { 404 RemoveEventHandler(exitRaelEventHandlerRef); 405 } 406 if (exitRaelEventHandler) { 407 DisposeEventHandlerUPP(exitRaelEventHandler); 408 } 409 ) TK_ENDIF 410 return err; 411} 412 413#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 414/* 415 *---------------------------------------------------------------------- 416 * 417 * ExitRaelEventHandlerProc -- 418 * 419 * This procedure is the dummy event handler used to break out of 420 * RAEL via longjmp, it is called as the first ever event handler 421 * in RAEL by posting a high priority dummy event. 422 * 423 * Results: 424 * None. Never returns ! 425 * 426 * Side effects: 427 * longjmp back to InstallStandardApplicationEventHandler(). 428 * 429 *---------------------------------------------------------------------- 430 */ 431 432static void 433ExitRaelEventHandlerProc( 434 EventHandlerCallRef callRef, 435 EventRef event, 436 void *userData) 437{ 438 longjmp(exitRaelJmpBuf, 1); 439} 440#endif 441 442/* 443 *---------------------------------------------------------------------- 444 * 445 * TkMacOSXRunTclEventLoop -- 446 * 447 * Process a limited number of tcl events. 448 * 449 * Results: 450 * Returns 1 if events were handled and 0 otherwise. 451 * 452 * Side effects: 453 * Runs the Tcl event loop. 454 * 455 *---------------------------------------------------------------------- 456 */ 457 458MODULE_SCOPE int 459TkMacOSXRunTclEventLoop(void) 460{ 461 int i = 4, result = 0; 462 463 /* Avoid starving main event loop: process at most 4 events. */ 464 while(--i && Tcl_ServiceAll()) { 465 result = 1; 466 } 467 return result; 468} 469 470/* 471 *---------------------------------------------------------------------- 472 * 473 * CarbonTimerProc -- 474 * 475 * This procedure is the carbon timer handler that runs the tcl 476 * event loop periodically. 477 * 478 * Results: 479 * None. 480 * 481 * Side effects: 482 * Runs the Tcl event loop. 483 * 484 *---------------------------------------------------------------------- 485 */ 486 487static void 488CarbonTimerProc( 489 EventLoopTimerRef timer, 490 void *userData) 491{ 492 if(carbonTimerEnabled > 0 && TkMacOSXRunTclEventLoop()) { 493#ifdef TK_MAC_DEBUG_CARBON_EVENTS 494 TkMacOSXDbgMsg("Processed tcl events from carbon timer"); 495#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 496 } 497} 498 499/* 500 *---------------------------------------------------------------------- 501 * 502 * TkMacOSXStartTclEventLoopCarbonTimer -- 503 * 504 * This procedure installs (if necessary) and starts a carbon 505 * event timer that runs the tcl event loop periodically. 506 * It should be called whenever a nested carbon event loop might 507 * run by HIToolbox (e.g. during mouse tracking) to ensure that 508 * tcl events continue to be processed. 509 * 510 * Results: 511 * OS status code. 512 * 513 * Side effects: 514 * Carbon event timer is installed and started. 515 * 516 *---------------------------------------------------------------------- 517 */ 518 519MODULE_SCOPE OSStatus 520TkMacOSXStartTclEventLoopCarbonTimer(void) 521{ 522 OSStatus err = noErr; 523 524 if (++carbonTimerEnabled > 0) { 525 if(!carbonTimer) { 526 EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(CarbonTimerProc); 527 528 err = ChkErr(InstallEventLoopTimer, GetMainEventLoop(), 529 5 * kEventDurationMillisecond, 530 5 * kEventDurationMillisecond, 531 timerUPP, NULL, &carbonTimer); 532 } else { 533 err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, 534 5 * kEventDurationMillisecond); 535 } 536 } 537 return err; 538} 539 540/* 541 *---------------------------------------------------------------------- 542 * 543 * TkMacOSXStopTclEventLoopCarbonTimer -- 544 * 545 * This procedure stops the carbon event timer started by 546 * TkMacOSXStartTclEventLoopCarbonTimer(). 547 * 548 * Results: 549 * OS status code. 550 * 551 * Side effects: 552 * Carbon event timer is stopped. 553 * 554 *---------------------------------------------------------------------- 555 */ 556 557MODULE_SCOPE OSStatus 558TkMacOSXStopTclEventLoopCarbonTimer(void) 559{ 560 OSStatus err = noErr; 561 562 if (--carbonTimerEnabled == 0) { 563 if(carbonTimer) { 564 err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, 565 kEventDurationForever); 566 } 567 } 568 return err; 569} 570 571/* 572 *---------------------------------------------------------------------- 573 * 574 * TkMacOSXTrackingLoop -- 575 * 576 * Call with 1 before entering a mouse tracking loop (e.g. window 577 * resizing or menu tracking) to enable tcl event processing but 578 * disable carbon event processing (except for update events) 579 * during the loop, and with 0 after exiting the loop to reset. 580 * 581 * Results: 582 * None. 583 * 584 * Side effects: 585 * None. 586 * 587 *---------------------------------------------------------------------- 588 */ 589 590MODULE_SCOPE void 591TkMacOSXTrackingLoop(int tracking) 592{ 593 static int previousServiceMode = TCL_SERVICE_NONE; 594 595 if (tracking) { 596 inTrackingLoop++; 597 previousServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); 598 TkMacOSXStartTclEventLoopCarbonTimer(); 599#ifdef TK_MAC_DEBUG_CARBON_EVENTS 600 TkMacOSXDbgMsg("Entering tracking loop"); 601#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 602 } else { 603 TkMacOSXStopTclEventLoopCarbonTimer(); 604 previousServiceMode = Tcl_SetServiceMode(previousServiceMode); 605 inTrackingLoop--; 606#ifdef TK_MAC_DEBUG_CARBON_EVENTS 607 TkMacOSXDbgMsg("Exiting tracking loop"); 608#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 609 } 610} 611 612/* 613 *---------------------------------------------------------------------- 614 * 615 * TkMacOSXReceiveAndDispatchEvent -- 616 * 617 * This receives a carbon event and sends it to the carbon event 618 * dispatcher. 619 * 620 * Results: 621 * Mac OS status 622 * 623 * Side effects: 624 * This receives and dispatches the next Carbon event. 625 * 626 *---------------------------------------------------------------------- 627 */ 628MODULE_SCOPE OSStatus 629TkMacOSXReceiveAndDispatchEvent(void) 630{ 631 static EventTargetRef targetRef = NULL; 632 int numEventTypes = 0; 633 const EventTypeSpec *eventTypes = NULL; 634 EventRef eventRef; 635 OSStatus err; 636 const EventTypeSpec trackingEventTypes[] = { 637 {'dniw', kEventWindowUpdate}, 638 {kEventClassWindow, kEventWindowUpdate}, 639 }; 640 641 if (inTrackingLoop > 0) { 642 eventTypes = trackingEventTypes; 643 numEventTypes = GetEventTypeCount(trackingEventTypes); 644 } 645 646 /* 647 * This is a poll, since we have already counted the events coming 648 * into this routine, and are guaranteed to have one waiting. 649 */ 650 651 err = ReceiveNextEvent(numEventTypes, eventTypes, 652 kEventDurationNoWait, true, &eventRef); 653 if (err == noErr) { 654#ifdef TK_MAC_DEBUG_CARBON_EVENTS 655 UInt32 kind = GetEventKind(eventRef); 656 657 if (kind != kEventMouseMoved && kind != kEventMouseDragged) { 658 TkMacOSXDbgMsg("Dispatching %s", TkMacOSXCarbonEventToAscii(eventRef)); 659 TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, 660 EventRef inEvent); 661 if (_DebugPrintEvent) { 662 /* Carbon-internal event debugging (c.f. Technote 2124) */ 663 _DebugPrintEvent(eventRef); 664 } 665 } 666#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ 667 if (!targetRef) { 668 targetRef = GetEventDispatcherTarget(); 669 } 670 TkMacOSXStartTclEventLoopCarbonTimer(); 671 err = SendEventToEventTarget(eventRef, targetRef); 672 TkMacOSXStopTclEventLoopCarbonTimer(); 673 if (err != noErr && err != eventLoopTimedOutErr 674 && err != eventNotHandledErr) { 675 TkMacOSXDbgMsg("SendEventToEventTarget(%s) failed: %ld", 676 TkMacOSXCarbonEventToAscii(eventRef), err); 677 } 678 ReleaseEvent(eventRef); 679 } else if (err != eventLoopTimedOutErr) { 680 TkMacOSXDbgMsg("ReceiveNextEvent failed: %ld", err); 681 } 682 return err; 683} 684