Posted to tcl by patthoyts at Tue Jan 05 01:08:03 GMT 2010view raw
- If you create a toplevel and make it transient without giving the
- master window a chance to be mapped first, then on X11 the transient
- state is never set and the window manager is never told to treat the
- toplevel as a transient window.
- This patch solves this by marking the window wrapper with a pending
- flag that causes the transient property to be set when the toplevel
- gets mapped finally. Addresses [Bug 1163496]
- Currently the decoration for the transient toplevel is wrong but the
- behaviour is correct. It seems the window manager does not refresh
- the decoration once the window has been mapped.
- Sample script:
- package require Tk
- variable uid 0
- proc mkdlg {} {
- variable uid
- set dlg [toplevel .dlg[incr uid]]
- wm transient $dlg .
- wm title $dlg "Transient $uid"
- return $dlg
- }
- mkdlg
- pack [ttk::button .b1 -text "New dialog" -command mkdlg]
- wm geometry . 200x200
- tkwait window .
- exit
- Index: unix/tkUnixWm.c
- ===================================================================
- RCS file: /cvsroot/tktoolkit/tk/unix/tkUnixWm.c,v
- retrieving revision 1.77
- diff -u -p -r1.77 tkUnixWm.c
- --- unix/tkUnixWm.c 9 Dec 2009 13:55:14 -0000 1.77
- +++ unix/tkUnixWm.c 5 Jan 2010 00:55:28 -0000
- @@ -261,6 +261,9 @@ typedef struct TkWmInfo {
- * WM_WITHDRAWN - non-zero means that this window has explicitly
- * been withdrawn. If it's a transient, it should
- * not mirror state changes in the master.
- + * WM_TRANSIENT_PENDING - marks a window that is transient for a master
- + * but the window manager hints have not yet
- + * been set. Handled when the window is mapped.
- */
- #define WM_NEVER_MAPPED 1
- @@ -277,6 +280,7 @@ typedef struct TkWmInfo {
- #define WM_WIDTH_NOT_RESIZABLE 0x1000
- #define WM_HEIGHT_NOT_RESIZABLE 0x2000
- #define WM_WITHDRAWN 0x4000
- +#define WM_TRANSIENT_PENDING 0x8000
- /*
- * This module keeps a list of all top-level windows, primarily to simplify
- @@ -676,6 +680,7 @@ TkWmMapWindow(
- if (!Tk_IsMapped(wmPtr->masterPtr)) {
- wmPtr->withdrawn = 1;
- wmPtr->hints.initial_state = WithdrawnState;
- + wmPtr->flags |= WM_TRANSIENT_PENDING;
- } else {
- XSetTransientForHint(winPtr->display,
- wmPtr->wrapperPtr->window,
- @@ -730,6 +735,16 @@ TkWmMapWindow(
- UpdateGeometryInfo(winPtr);
- return;
- }
- +
- + if (wmPtr->flags & WM_TRANSIENT_PENDING) {
- + wmPtr->flags &= ~WM_TRANSIENT_PENDING;
- + if (wmPtr->masterPtr != NULL) {
- + XSetTransientForHint(winPtr->display,
- + wmPtr->wrapperPtr->window,
- + wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
- + }
- + }
- +
- wmPtr->flags |= WM_ABOUT_TO_MAP;
- if (wmPtr->flags & WM_UPDATE_PENDING) {
- Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);