From: SourceForge.net <no...@so...> - 2003-11-12 23:42:03
|
Bugs item #220887, was opened at 2000-10-31 20:30 Message generated for change (Settings changed) made by dgp You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=112997&aid=220887&group_id=12997 Category: 13. Win Menus Group: obsolete: 8.2.2 Status: Open Resolution: None Priority: 5 Submitted By: Brent B. Welch (welch) >Assigned to: Jeffrey Hobbs (hobbs) Summary: Popup-menus may fail if using threads Initial Comment: OriginalBugID: 3921 Bug Version: 8.2.2 SubmitDate: '1999-12-22' LastModified: '2000-01-25' Severity: SER Status: UnAssn Submitter: techsupp ChangedBy: hobbs OS: Windows NT OSVersion: NT4.0 ServicePack6 Machine: intel PC Name: Dr. Lukas Rosenthaler Extensions: img1.2, incr tcl CustomShell: with exception of patch above no other Comments: The cause of the problem is as follows: The window for the popup menu is initialized in TkpMenuInit. The window handle is stored in a thread specific data area (using Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); ). If the thread exits, the thread specific data is lost, and so the popup menu's window handle. However, starting a new thread doesn't invoke TkpMenuInit anymore. Then the WIN32-function TrackPopupMenu (called from within TkpPostMenu) receives an invalid window handle and returns immediately (The new, patched version will check the return value of TrackPopupMenu and issue an error, if something's wrong). Solution to the Problem: The code to create the popup menu's window has been moved to TkpMenuThreadInit. Within TkpMenuThreadInit, an exit-handler using "Tcl_CreateThreadExitHandler(MenuExitHandler, (ClientData) NULL);" has been added to destroy the menu-window if the thread exits. Tests (all compiled with "/DTCL_THREADS=1" !) have shown no side-effects of this patch. ReproducibleScript: Embedded Tcl/Tk in a threaded environment. The application (using it's own non-tcl windows based event loop) launches Tcl/Tk-threads which have their own toplevel windows and own event loops. ObservedBehavior: When using threads, the popup of menus doesn't work properly. The first time a thread is invoked, popup menus work fine, but if the first thread exits using Tcl_ThreadExit (0), and later a second thread is invoked, then the popup menus don't work anymore. DesiredBehavior: popup menu should work properly... Patch: *** tkWinMenu-orig.c Wed Sep 22 08:53:24 1999 --- tkWinMenu.c Wed Dec 22 11:54:24 1999 *************** *** 778,785 **** } } ! TrackPopupMenu(winMenuHdl, flags, x, y, 0, ! tsdPtr->menuHWND, &noGoawayRect); Tcl_SetServiceMode(oldServiceMode); GetCursorPos(&point); --- 778,794 ---- } } ! if (TrackPopupMenu(winMenuHdl, flags, x, y, 0, ! tsdPtr->menuHWND, &noGoawayRect) == 0) { ! LPVOID lpMsgBuf; ! char errstr[1024]; ! FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, ! NULL, GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), ! (LPTSTR) &lpMsgBuf, 0, NULL); ! sprintf (errstr, "[%s: #%04d] ERROR: TrackPopupMenu failed!\n%s", ! __FILE__, __LINE__, (char *) lpMsgBuf); ! MessageBox (NULL, errstr, "Tk Internal Error", MB_OK | MB_ICONERROR); ! } Tcl_SetServiceMode(oldServiceMode); GetCursorPos(&point); *************** *** 2789,2814 **** void TkpMenuInit() { - WNDCLASS wndClass; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - wndClass.style = CS_OWNDC; - wndClass.lpfnWndProc = TkWinMenuProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = 0; - wndClass.hInstance = Tk_GetHINSTANCE(); - wndClass.hIcon = NULL; - wndClass.hCursor = NULL; - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszMenuName = NULL; - wndClass.lpszClassName = MENU_CLASS_NAME; - RegisterClass(&wndClass); - - tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP, - 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL); - - Tcl_CreateExitHandler(MenuExitHandler, (ClientData) NULL); SetDefaults(1); } --- 2798,2804 ---- *************** *** 2831,2838 **** --- 2821,2848 ---- void TkpMenuThreadInit() { + WNDCLASS wndClass; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + + wndClass.style = CS_OWNDC; + wndClass.lpfnWndProc = TkWinMenuProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = Tk_GetHINSTANCE(); + wndClass.hIcon = NULL; + wndClass.hCursor = NULL; + wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = MENU_CLASS_NAME; + RegisterClass(&wndClass); + + tsdPtr->menuHWND = CreateWindow(MENU_CLASS_NAME, "MenuWindow", WS_POPUP, + 0, 0, 10, 10, NULL, NULL, Tk_GetHINSTANCE(), NULL); + + Tcl_CreateThreadExitHandler(MenuExitHandler, (ClientData) NULL); + SetDefaults(0); Tcl_InitHashTable(&tsdPtr->winMenuTable, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&tsdPtr->commandTable, TCL_ONE_WORD_KEYS); PatchFiles: tkWinMenu.c ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=112997&aid=220887&group_id=12997 |