Tk Source Code

View Ticket
Login
Ticket UUID: adb71ed70b177298b900a1cd2ac0ae429c703aa3
Title: windows: after using tk_messageBox, parent window remains unresponsive
Type: Bug Version: 8.6.10
Submitter: bll Created on: 2019-12-10 17:24:26
Subsystem: 55. [focus] Assigned To: nobody
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2026-10-09 15:36:25
Resolution: Fixed Closed By: nemethi
    Closed on: 2026-10-09 15:36:25
Description:
Works ok on Linux.  Is the grab not being released properly on windows?

Reference:

https://stackoverflow.com/questions/59261636/tk-messagebox-is-showing-erroneous-display-in-grid-view-but-ok-in-pack?noredirect=1#comment104747351_59261636

package require Tk
wm title . "Message Box Demo"

tk::text .t0

grid .t0 -column 0 -row 1 -columnspan 2

tk_messageBox -type okcancel  -message "Press Ok to confirm" \
    -title "Update V 3.6" -icon "info"
User Comments: nemethi (claiming to be Csaba Nemethi) added on 2026-10-09 15:36:25:

Serhiy, many thanks for the fix! Merged into main, core-9-0-branch, and core-8-6-branch by commits [c487406d], [01bf2744], and [7de1b478].


serhiy.storchaka added on 2026-09-18 19:03:28:

Reproduced on Windows 11 with 8.6.18 and 9.1, also with tk_getOpenFile.

The dialog disables its owner, the window of the not yet mapped parent toplevel. The toplevel is mapped while the dialog is open, and its window is reparented into the new wrapper. On close the dialog re-enables and activates the wrapper, and the focus stays on the wrapper, because the disabled window cannot receive it. The existing EnableWindow() call after the dialog enables the window, but nothing gives it the focus, so Tk never gets a FocusIn event and displayFocusPtr->focusWinPtr remains NULL.

Fix in branch [d8d65f6671]: move the focus to the re-enabled window.


fvogel added on 2019-12-21 15:32:02:

Just noticed this problem has been reported previously: [df09b0665c]

From further diving into the source code:

- The issue shows up when the code packs/grids any widget and just after opens any message box (tk_chooseColor, tk_getOpenFile, tk_messageBox...)
- When clicking in the widget to give it the focus, nothing happens because displayFocusPtr->focusWinPtr is NULL. TkSetFocusWin does nothing for this reason.

So to fix this we could add the -force flag to the focus command executed when the user clicks in the widget.

Perhaps we should understand why displayFocusPtr->focusWinPtr is NULL at this point. From the previous observations with Tcl_SetServiceMode() I suspect something wrong in the events servicing but it's not easy to identify what exactly.


fvogel added on 2019-12-18 21:12:25:
> Does moving the calls to only bracket messageboxw() fix anything?

It doesn't.

I didn't make it clear, but I don't like my both patches :-)

bll added on 2019-12-17 21:49:07:
Looks like Tcl_SetServiceMode() calls are wrapped around many of the dialogs
in the windows code, and a couple spots in Mac.

Something to do with threads apparently.

I do not like patch 2.

Seems like in the other routines the Tcl_SetServiceMode() pair brackets a 
smaller amount of code.

Does moving the calls to only bracket messageboxw() fix anything?
    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
    winCode = MessageBoxW (...);
    Tcl_SetServiceMode(oldMode);
fix the issue?

fvogel added on 2019-12-17 21:18:49:

Debugging.

This happens on Windows only, not on the Mac (I tried) nor on Linux (you stated it).

Either of the following two patches fixes the problem:

Patch 1:

Index: win/tkWinDialog.c
==================================================================
--- win/tkWinDialog.c
+++ win/tkWinDialog.c
@@ -2912,10 +2912,11 @@
 	Tcl_AppendStringsToObj(tmpObj, "\n\n", NULL);
 	Tcl_AppendObjToObj(tmpObj, detailObj);
     }
 
     oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
+    Tcl_ServiceAll();
 
     /*
      * MessageBoxW exists for all platforms. Use it to allow unicode error
      * message to be displayed correctly where possible by the OS.
      *

Patch 2:

Index: win/tkWinDialog.c
==================================================================
--- win/tkWinDialog.c
+++ win/tkWinDialog.c
@@ -2783,11 +2783,11 @@
 {
     Tk_Window tkwin = clientData, parent;
     HWND hWnd;
     Tcl_Obj *messageObj, *titleObj, *detailObj, *tmpObj;
     int defaultBtn, icon, type;
-    int i, oldMode, winCode;
+    int i, winCode;
     UINT flags;
     static const char *const optionStrings[] = {
 	"-default",	"-detail",	"-icon",	"-message",
 	"-parent",	"-title",	"-type",	NULL
     };
@@ -2911,11 +2911,10 @@
     if (detailObj) {
 	Tcl_AppendStringsToObj(tmpObj, "\n\n", NULL);
 	Tcl_AppendObjToObj(tmpObj, detailObj);
     }
 
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
 
     /*
      * MessageBoxW exists for all platforms. Use it to allow unicode error
      * message to be displayed correctly where possible by the OS.
      *
@@ -2939,11 +2938,10 @@
     }
     winCode = MessageBoxW(hWnd, tmpPtr, titlePtr, flags);
     Tcl_DStringFree(&titleBuf);
     Tcl_DStringFree(&tmpBuf);
     UnhookWindowsHookEx(tsdPtr->hMsgBoxHook);
-    (void) Tcl_SetServiceMode(oldMode);
 
     /*
      * Ensure that hWnd is enabled, because it can happen that we have updated
      * the wrapper of the parent, which causes us to leave this child disabled
      * (Windows loses sync).

I'm not sure I understand the need for these calls to Tcl_SetServiceMode(). They are in the source code from day 1 (1998).


bll added on 2019-12-15 21:44:49:
Excellent.  I sort of had in my mind to try an update, but forgot.

fvogel added on 2019-12-15 21:37:02:

Oh, and in the original report, it seems that several wrong statements are made. From my testing, the problem is the same for both [grid] and [pack], and also is the same with or without "-parent .", contrary to what is stated in the original report. Also, this is more a focus problem than a "disabled state" problem.


fvogel added on 2019-12-15 21:30:18:
Had an illumination and could reproduce on Vista.

The test script works as expected when pasted in tclsh.

The test script shows the problem when sourced in tclsh.

Obviously then, as one would expect, the test script works as expected when sourced in tclsh if an 'update' is added before the tk_messageBox command.

When the problem is triggered, the text widget becomes responsive again if the user clicks in another application and then in the widget again.

Finally this is an old problem. I can reproduce in 8.5.16.

bll added on 2019-12-15 17:40:40:
Tested with core-8-6-branch, fails.

bll added on 2019-12-11 13:30:16:
That's interesting.
The only big difference I can imagine is that I compiled with gcc (msys2),
and (I am assuming) you compiled woth VC,

fvogel added on 2019-12-11 09:19:32:
Sorry I'm still failing at seeing any issue. I tried on vista/64 and win10/64, with almost up to date versions on the source code. Running the example given in the present ticket, I click OK in the message box and I can enter text in the text widget as expected.

bll added on 2019-12-10 23:29:54:
Fails on win7/64, win10/32, vista/64.

bll added on 2019-12-10 21:05:04:
After clicking OK (or cancel) on the message box, the text widget cannot be accessed in the main window.  I was able to re-create with windows 7.

fvogel added on 2019-12-10 20:40:56:
Works flawlessly for me on Vista. Can't see any problem with the provided code.