diff options
author | culler <culler> | 2020-09-27 19:29:30 (GMT) |
---|---|---|
committer | culler <culler> | 2020-09-27 19:29:30 (GMT) |
commit | 48f3771a552ad6c5f6f07b86545757a2f92ba633 (patch) | |
tree | 66c76e1b3c0f8bd290ab9fb68d58d3a212dfc58b /macosx/tkMacOSXWm.c | |
parent | ed9cf42792f8332d1386414e459c9a4af9c66238 (diff) | |
parent | b0ff53377869ccfb7928d389f7bd6fdeddaca3f3 (diff) | |
download | tk-48f3771a552ad6c5f6f07b86545757a2f92ba633.zip tk-48f3771a552ad6c5f6f07b86545757a2f92ba633.tar.gz tk-48f3771a552ad6c5f6f07b86545757a2f92ba633.tar.bz2 |
Fix aqua MapNotify and UnmapNotify
Diffstat (limited to 'macosx/tkMacOSXWm.c')
-rw-r--r-- | macosx/tkMacOSXWm.c | 96 |
1 files changed, 93 insertions, 3 deletions
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 3bc12d7..e971319 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -746,6 +746,74 @@ TkWmNewWindow( /* *---------------------------------------------------------------------- * + * TkMacOSXHandleMapOrUnmap -- + * + * The mechanism used by a geometry manager to propogate the information + * about which of its content widgets are mapped is to call Tk_MapWindow + * or Tk_UnmapNotify. Those functions generate MapNotify or UnmapNotify + * events and then handle them immediately. Other platforms use + * Tk_HandleEvent to do this. But that does not work correctly on macOS + * due to the fact that the calls to Tk_MapNotify or Tk_UnmapNotify can + * occur in display procedures which are being run in the drawRect method + * of a TKContentView. The events will be processed after drawRect + * returns, but they need to be processed immediately in some cases. + + * This function operates as a macOS alternative to Tk_HandleEvent, for + * processing MapNotify or UnmapNotify events only. It is called by + * Tk_MapWindow, Tk_UnmapWindow, TkWmMapWindow and TkWmUnmapWindow. + * Rather than using Tk_HandleEvent it installs a filter which restricts + * to the MapNotify or UnmapNotify events, it queues the event and then + * processes window events with the filter installed. This allows the + * event to be handled immediately even from within the drawRect method. + * + * Results: + * None. + * + * Side effects: + * Handles a MapNotify or UnMapNotify event. + * + *---------------------------------------------------------------------- + */ +static Tk_RestrictAction +MapUnmapRestrictProc( + ClientData arg, + XEvent *eventPtr) +{ + return (eventPtr->type==MapNotify || eventPtr->type==UnmapNotify ? + TK_PROCESS_EVENT : TK_DEFER_EVENT); +} + +MODULE_SCOPE +void TkMacOSXHandleMapOrUnmap( + Tk_Window tkwin, + XEvent *event) +{ + ClientData oldArg; + Tk_RestrictProc *oldProc; + TkWindow *winPtr = (TkWindow *) tkwin; + const Tk_GeomMgr *geomMgrPtr = winPtr->geomMgrPtr; + + /* + * Sadly, this approach does not work with the "text" geometry manager. + * The mysterious unexplained crash elicited by textDisp-5.2 occurs. So we + * have to check for the "text" manager and revert to using Tk_HandleEvent + * in that case. Hopefully this can be removed when the revised text + * widget is in place. + */ + + if (geomMgrPtr && strcmp(geomMgrPtr->name, "text") == 0) { + Tk_HandleEvent(event); + return; + } + oldProc = Tk_RestrictEvents(MapUnmapRestrictProc, NULL, &oldArg); + Tk_QueueWindowEvent(event, TCL_QUEUE_TAIL); + while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {} + Tk_RestrictEvents(oldProc, oldArg, &oldArg); +} + +/* + *---------------------------------------------------------------------- + * * TkWmMapWindow -- * * This procedure is invoked to map a top-level window. This module gets @@ -772,6 +840,8 @@ TkWmMapWindow( * mapped. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; + XEvent event; + if (wmPtr->flags & WM_NEVER_MAPPED) { /* * Create the underlying Mac window for this Tk window. @@ -835,10 +905,19 @@ TkWmMapWindow( wmPtr->flags &= ~WM_ABOUT_TO_MAP; /* - * Map the window. + * Map the window and process a MapNotify event for it. */ + winPtr->flags |= TK_MAPPED; XMapWindow(winPtr->display, winPtr->window); + event.xany.serial = LastKnownRequestProcessed(winPtr->display); + event.xany.send_event = False; + event.xany.display = winPtr->display; + event.xmap.window = winPtr->window; + event.xmap.type = MapNotify; + event.xmap.event = winPtr->window; + event.xmap.override_redirect = winPtr->atts.override_redirect; + TkpHandleMapOrUnmap((Tk_Window)winPtr, &event); } /* @@ -863,7 +942,18 @@ TkWmUnmapWindow( TkWindow *winPtr) /* Top-level window that's about to be * unmapped. */ { + XEvent event; + + event.xany.serial = LastKnownRequestProcessed(winPtr->display); + event.xany.send_event = False; + event.xany.display = winPtr->display; + event.xunmap.type = UnmapNotify; + event.xunmap.window = winPtr->window; + event.xunmap.event = winPtr->window; + event.xunmap.from_configure = false; + winPtr->flags &= ~TK_MAPPED; XUnmapWindow(winPtr->display, winPtr->window); + TkpHandleMapOrUnmap((Tk_Window)winPtr, &event); } /* @@ -6943,9 +7033,9 @@ ApplyContainerOverrideChanges( if (parentWindow && parentWindow != containerMacWin) { [parentWindow removeChildWindow:macWindow]; } - + [macWindow orderFront:NSApp]; [containerMacWin addChildWindow:macWindow - ordered:NSWindowAbove]; + ordered:NSWindowAbove]; } } } else { |