tkMacOSXNotify.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXNotify.c --
  3.  *
  4.  * This file contains the implementation of a tcl event source
  5.  * for the Carbon event loop.
  6.  *
  7.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  8.  * Copyright 2001, Apple Computer, Inc.
  9.  * Copyright (c) 2005-2007 Daniel A. Steffen <das@users.sourceforge.net>
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * RCS: @(#) $Id: tkMacOSXNotify.c,v 1.5.2.12 2007/06/29 03:22:02 das Exp $
  15.  */
  16. #include "tkMacOSXPrivate.h"
  17. #include "tkMacOSXEvent.h"
  18. #include <pthread.h>
  19. /*
  20.  * The following static indicates whether this module has been initialized
  21.  * in the current thread.
  22.  */
  23. typedef struct ThreadSpecificData {
  24.     int initialized;
  25. } ThreadSpecificData;
  26. static Tcl_ThreadDataKey dataKey;
  27. static void TkMacOSXNotifyExitHandler(ClientData clientData);
  28. static void CarbonEventsSetupProc(ClientData clientData, int flags);
  29. static void CarbonEventsCheckProc(ClientData clientData, int flags);
  30. /*
  31.  *----------------------------------------------------------------------
  32.  *
  33.  * Tk_MacOSXSetupTkNotifier --
  34.  *
  35.  * This procedure is called during Tk initialization to create
  36.  * the event source for Carbon events.
  37.  *
  38.  * Results:
  39.  * None.
  40.  *
  41.  * Side effects:
  42.  * A new event source is created.
  43.  *
  44.  *----------------------------------------------------------------------
  45.  */
  46. void
  47. Tk_MacOSXSetupTkNotifier(void)
  48. {
  49.     ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey,
  50.     sizeof(ThreadSpecificData));
  51.     if (!tsdPtr->initialized) {
  52. /* HACK ALERT: There is a bug in Jaguar where when it goes to make
  53.  * the event queue for the Main Event Loop, it stores the Current
  54.  * event loop rather than the Main Event Loop in the Queue structure.
  55.  * So we have to make sure that the Main Event Queue gets set up on
  56.  * the main thread. Calling GetMainEventQueue will force this to
  57.  * happen.
  58.  */
  59. GetMainEventQueue();
  60. tsdPtr->initialized = 1;
  61. /* Install Carbon events event source in main event loop thread. */
  62. if (GetCurrentEventLoop() == GetMainEventLoop()) {
  63.     if (!pthread_main_np()) {
  64. /*
  65.  * Panic if the Carbon main event loop thread (i.e. the
  66.  * thread  where HIToolbox was first loaded) is not the
  67.  * main application thread, as Carbon does not support
  68.  * this properly.
  69.  */
  70. Tcl_Panic("Tk_MacOSXSetupTkNotifier: %s",
  71.     "first [load] of TkAqua has to occur in the main thread!");
  72.     }
  73.     Tcl_CreateEventSource(CarbonEventsSetupProc,
  74.     CarbonEventsCheckProc, GetMainEventQueue());
  75.     TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
  76. }
  77.     }
  78. }
  79. /*
  80.  *----------------------------------------------------------------------
  81.  *
  82.  * TkMacOSXNotifyExitHandler --
  83.  *
  84.  * This function is called during finalization to clean up the
  85.  * TkMacOSXNotify module.
  86.  *
  87.  * Results:
  88.  * None.
  89.  *
  90.  * Side effects:
  91.  * None.
  92.  *
  93.  *----------------------------------------------------------------------
  94.  */
  95. static void
  96. TkMacOSXNotifyExitHandler(clientData)
  97.     ClientData clientData; /* Not used. */
  98. {
  99.     ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey,
  100.     sizeof(ThreadSpecificData));
  101.     Tcl_DeleteEventSource(CarbonEventsSetupProc,
  102.     CarbonEventsCheckProc, GetMainEventQueue());
  103.     tsdPtr->initialized = 0;
  104. }
  105. /*
  106.  *----------------------------------------------------------------------
  107.  *
  108.  * CarbonEventsSetupProc --
  109.  *
  110.  * This procedure implements the setup part of the Carbon Events
  111.  * event source. It is invoked by Tcl_DoOneEvent before entering
  112.  * the notifier to check for events.
  113.  *
  114.  * Results:
  115.  * None.
  116.  *
  117.  * Side effects:
  118.  * If Carbon events are queued, then the maximum block time will be
  119.  * set to 0 to ensure that the notifier returns control to Tcl.
  120.  *
  121.  *----------------------------------------------------------------------
  122.  */
  123. static void
  124. CarbonEventsSetupProc(clientData, flags)
  125.     ClientData clientData;
  126.     int flags;
  127. {
  128.     static Tcl_Time blockTime = { 0, 0 };
  129.     if (!(flags & TCL_WINDOW_EVENTS)) {
  130. return;
  131.     }
  132.     if (GetNumEventsInQueue((EventQueueRef)clientData)) {
  133. Tcl_SetMaxBlockTime(&blockTime);
  134.     }
  135. }
  136. /*
  137.  *----------------------------------------------------------------------
  138.  *
  139.  * CarbonEventsCheckProc --
  140.  *
  141.  * This procedure processes events sitting in the Carbon event
  142.  * queue.
  143.  *
  144.  * Results:
  145.  * None.
  146.  *
  147.  * Side effects:
  148.  * Moves applicable queued Carbon events onto the Tcl event queue.
  149.  *
  150.  *----------------------------------------------------------------------
  151.  */
  152. static void
  153. CarbonEventsCheckProc(clientData, flags)
  154.     ClientData clientData;
  155.     int flags;
  156. {
  157.     int numFound;
  158.     OSStatus err = noErr;
  159.     if (!(flags & TCL_WINDOW_EVENTS)) {
  160. return;
  161.     }
  162.     numFound = GetNumEventsInQueue((EventQueueRef)clientData);
  163.     /* Avoid starving other event sources: */
  164.     if (numFound > 4) {
  165. numFound = 4;
  166.     }
  167.     while (numFound > 0 && err == noErr) {
  168. err = TkMacOSXReceiveAndDispatchEvent();
  169. numFound--;
  170.     }
  171. }