Posted to tcl by patthoyts at Tue Jan 05 01:08:03 GMT 2010view raw

  1. If you create a toplevel and make it transient without giving the
  2. master window a chance to be mapped first, then on X11 the transient
  3. state is never set and the window manager is never told to treat the
  4. toplevel as a transient window.
  5.  
  6. This patch solves this by marking the window wrapper with a pending
  7. flag that causes the transient property to be set when the toplevel
  8. gets mapped finally. Addresses [Bug 1163496]
  9.  
  10. Currently the decoration for the transient toplevel is wrong but the
  11. behaviour is correct. It seems the window manager does not refresh
  12. the decoration once the window has been mapped.
  13.  
  14. Sample script:
  15.  
  16. package require Tk
  17. variable uid 0
  18. proc mkdlg {} {
  19. variable uid
  20. set dlg [toplevel .dlg[incr uid]]
  21. wm transient $dlg .
  22. wm title $dlg "Transient $uid"
  23. return $dlg
  24. }
  25. mkdlg
  26. pack [ttk::button .b1 -text "New dialog" -command mkdlg]
  27. wm geometry . 200x200
  28. tkwait window .
  29. exit
  30.  
  31.  
  32. Index: unix/tkUnixWm.c
  33. ===================================================================
  34. RCS file: /cvsroot/tktoolkit/tk/unix/tkUnixWm.c,v
  35. retrieving revision 1.77
  36. diff -u -p -r1.77 tkUnixWm.c
  37. --- unix/tkUnixWm.c 9 Dec 2009 13:55:14 -0000 1.77
  38. +++ unix/tkUnixWm.c 5 Jan 2010 00:55:28 -0000
  39. @@ -261,6 +261,9 @@ typedef struct TkWmInfo {
  40. * WM_WITHDRAWN - non-zero means that this window has explicitly
  41. * been withdrawn. If it's a transient, it should
  42. * not mirror state changes in the master.
  43. + * WM_TRANSIENT_PENDING - marks a window that is transient for a master
  44. + * but the window manager hints have not yet
  45. + * been set. Handled when the window is mapped.
  46. */
  47.  
  48. #define WM_NEVER_MAPPED 1
  49. @@ -277,6 +280,7 @@ typedef struct TkWmInfo {
  50. #define WM_WIDTH_NOT_RESIZABLE 0x1000
  51. #define WM_HEIGHT_NOT_RESIZABLE 0x2000
  52. #define WM_WITHDRAWN 0x4000
  53. +#define WM_TRANSIENT_PENDING 0x8000
  54.  
  55. /*
  56. * This module keeps a list of all top-level windows, primarily to simplify
  57. @@ -676,6 +680,7 @@ TkWmMapWindow(
  58. if (!Tk_IsMapped(wmPtr->masterPtr)) {
  59. wmPtr->withdrawn = 1;
  60. wmPtr->hints.initial_state = WithdrawnState;
  61. + wmPtr->flags |= WM_TRANSIENT_PENDING;
  62. } else {
  63. XSetTransientForHint(winPtr->display,
  64. wmPtr->wrapperPtr->window,
  65. @@ -730,6 +735,16 @@ TkWmMapWindow(
  66. UpdateGeometryInfo(winPtr);
  67. return;
  68. }
  69. +
  70. + if (wmPtr->flags & WM_TRANSIENT_PENDING) {
  71. + wmPtr->flags &= ~WM_TRANSIENT_PENDING;
  72. + if (wmPtr->masterPtr != NULL) {
  73. + XSetTransientForHint(winPtr->display,
  74. + wmPtr->wrapperPtr->window,
  75. + wmPtr->masterPtr->wmInfoPtr->wrapperPtr->window);
  76. + }
  77. + }
  78. +
  79. wmPtr->flags |= WM_ABOUT_TO_MAP;
  80. if (wmPtr->flags & WM_UPDATE_PENDING) {
  81. Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);