diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2012-06-23 07:10:06 (GMT) | 
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2012-06-23 07:10:06 (GMT) | 
| commit | b3d458c88e93d44e5a0ea594e7da1ed66fd816a4 (patch) | |
| tree | 604f9ee615167d13590b0c33c245b7a898e1ced5 /unix/tclUnixNotfy.c | |
| parent | e87f03c29d1158714d9319724311d1091997611d (diff) | |
| parent | 366ea66bb84ae5120d3dca0dc01fb7aa46fc9ee6 (diff) | |
| download | tcl-b3d458c88e93d44e5a0ea594e7da1ed66fd816a4.zip tcl-b3d458c88e93d44e5a0ea594e7da1ed66fd816a4.tar.gz tcl-b3d458c88e93d44e5a0ea594e7da1ed66fd816a4.tar.bz2 | |
[Bug 3508771]: Cygwin notifier for handling win32 events
Diffstat (limited to 'unix/tclUnixNotfy.c')
| -rw-r--r-- | unix/tclUnixNotfy.c | 145 | 
1 files changed, 144 insertions, 1 deletions
| diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index e7bf78d..904c9db 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -99,9 +99,16 @@ typedef struct ThreadSpecificData {  				 * from these pointers. You must hold the  				 * notifierMutex lock before accessing these  				 * fields. */ +#ifdef __CYGWIN__ +    void *event;     /* Any other thread alerts a notifier +	 * that an event is ready to be processed +	 * by sending this event. */ +    void *hwnd;			/* Messaging window. */ +#else /* !__CYGWIN__ */      Tcl_Condition waitCV;	/* Any other thread alerts a notifier that an  				 * event is ready to be processed by signaling  				 * this condition variable. */ +#endif /* __CYGWIN__ */      int eventReady;		/* True if an event is ready to be processed.  				 * Used as condition flag together with waitCV  				 * above. */ @@ -205,6 +212,48 @@ static int	FileHandlerEventProc(Tcl_Event *evPtr, int flags);   *----------------------------------------------------------------------   */ +#if defined(TCL_THREADS) && defined(__CYGWIN__) + +typedef struct { +    void *hwnd; +    unsigned int *message; +    int wParam; +    int lParam; +    int time; +    int x; +    int y; +} MSG; + +typedef struct { +  unsigned int style; +  void *lpfnWndProc; +  int cbClsExtra; +  int cbWndExtra; +  void *hInstance; +  void *hIcon; +  void *hCursor; +  void *hbrBackground; +  void *lpszMenuName; +  void *lpszClassName; +} WNDCLASS; + +extern unsigned char __stdcall PeekMessageW(MSG *, void *, int, int, int); +extern unsigned char __stdcall GetMessageW(MSG *, void *, int, int); +extern unsigned char __stdcall TranslateMessage(const MSG *); +extern int __stdcall DispatchMessageW(const MSG *); +extern void __stdcall PostQuitMessage(int); +extern void * __stdcall CreateWindowExW(void *, void *, void *, DWORD, int, int, int, int, void *, void *, void *, void *); +extern unsigned char __stdcall DestroyWindow(void *); +extern unsigned char __stdcall PostMessageW(void *, unsigned int, void *, void *); +extern void *__stdcall RegisterClassW(const WNDCLASS *); +extern DWORD __stdcall DefWindowProcW(void *, int, void *, void *); +extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char, void *); +extern void __stdcall CloseHandle(void *); +extern void __stdcall MsgWaitForMultipleObjects(DWORD, void *, unsigned char, DWORD, DWORD); +extern unsigned char __stdcall ResetEvent(void *); + +#endif +  ClientData  Tcl_InitNotifier(void)  { @@ -308,7 +357,11 @@ Tcl_FinalizeNotifier(       * Clean up any synchronization objects in the thread local storage.       */ +#ifdef __CYGWIN__ +    CloseHandle(tsdPtr->event); +#else /* __CYGWIN__ */      Tcl_ConditionFinalize(&(tsdPtr->waitCV)); +#endif /* __CYGWIN__ */      Tcl_MutexUnlock(¬ifierMutex);  #endif @@ -341,7 +394,11 @@ Tcl_AlertNotifier(      ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;      Tcl_MutexLock(¬ifierMutex);      tsdPtr->eventReady = 1; +#ifdef __CYGWIN__ +    PostMessageW(tsdPtr->hwnd, 1024, 0, 0); +#else      Tcl_ConditionNotify(&tsdPtr->waitCV); +#endif      Tcl_MutexUnlock(¬ifierMutex);  #endif  } @@ -641,6 +698,31 @@ FileHandlerEventProc(      return 1;  } +#if defined(TCL_THREADS) && defined(__CYGWIN__) + +static DWORD __stdcall +NotifierProc( +    void *hwnd, +    unsigned int message, +    void *wParam, +    void *lParam) +{ +    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + +    if (message != 1024) { +	return DefWindowProcW(hwnd, message, wParam, lParam); +    } + +    /* +     * Process all of the runnable events. +     */ + +	tsdPtr->eventReady = 1; +    Tcl_ServiceAll(); +    return 0; +} +#endif /* __CYGWIN__ */ +  /*   *----------------------------------------------------------------------   * @@ -669,6 +751,9 @@ Tcl_WaitForEvent(      Tcl_Time vTime;  #ifdef TCL_THREADS      int waitForFiles; +# ifdef __CYGWIN__ +    MSG msg; +# endif  #else      /*       * Impl. notes: timeout & timeoutPtr are used if, and only if threads are @@ -756,6 +841,29 @@ Tcl_WaitForEvent(  	tsdPtr->pollState = 0;      } +#ifdef __CYGWIN__ +	if (!tsdPtr->hwnd) { +		WNDCLASS class; + +	    class.style = 0; +	    class.cbClsExtra = 0; +	    class.cbWndExtra = 0; +	    class.hInstance = TclWinGetTclInstance(); +	    class.hbrBackground = NULL; +	    class.lpszMenuName = NULL; +	    class.lpszClassName = L"TclNotifier"; +	    class.lpfnWndProc = NotifierProc; +	    class.hIcon = NULL; +	    class.hCursor = NULL; + +	    RegisterClassW(&class); +	    tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName, class.lpszClassName, +		    0, 0, 0, 0, 0, NULL, NULL, TclWinGetTclInstance(), NULL); +	    tsdPtr->event = CreateEventW(NULL, 1 /* manual */, +		    0 /* !signaled */, NULL); +    } + +#endif      if (waitForFiles) {  	/*  	 * Add the ThreadSpecificData structure of this thread to the list of @@ -781,10 +889,41 @@ Tcl_WaitForEvent(      FD_ZERO(&(tsdPtr->readyMasks.exceptional));      if (!tsdPtr->eventReady) { +#ifdef __CYGWIN__ +	if (!PeekMessageW(&msg, NULL, 0, 0, 0)) { +	    DWORD timeout; +	    if (timePtr) { +		timeout = timePtr->sec * 1000 + timePtr->usec / 1000; +	    } else { +		timeout = 0xFFFFFFFF; +	    } +	    Tcl_MutexUnlock(¬ifierMutex); +	    MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279); +	    Tcl_MutexLock(¬ifierMutex); +	} +#else  	Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr); +#endif      }      tsdPtr->eventReady = 0; +#ifdef __CYGWIN__ +    while (PeekMessageW(&msg, NULL, 0, 0, 0)) { +	/* +	 * Retrieve and dispatch the message. +	 */ +	DWORD result = GetMessageW(&msg, NULL, 0, 0); +	if (result == 0) { +	    PostQuitMessage(msg.wParam); +	    /* What to do here? */ +	} else if (result != (DWORD)-1) { +	    TranslateMessage(&msg); +	    DispatchMessageW(&msg); +	} +    } +    ResetEvent(tsdPtr->event); +#endif +      if (waitForFiles && tsdPtr->onList) {  	/*  	 * Remove the ThreadSpecificData structure of this thread from the @@ -1042,7 +1181,11 @@ NotifierThreadProc(  		    tsdPtr->onList = 0;  		    tsdPtr->pollState = 0;  		} -		Tcl_ConditionNotify(&tsdPtr->waitCV); +#ifdef __CYGWIN__ +	    PostMessageW(tsdPtr->hwnd, 1024, 0, 0); +#else /* __CYGWIN__ */ +	    Tcl_ConditionNotify(&tsdPtr->waitCV); +#endif /* __CYGWIN__ */  	    }  	}  	Tcl_MutexUnlock(¬ifierMutex); | 
