summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXWm.c
diff options
context:
space:
mode:
authorculler <culler>2020-09-27 19:29:30 (GMT)
committerculler <culler>2020-09-27 19:29:30 (GMT)
commit48f3771a552ad6c5f6f07b86545757a2f92ba633 (patch)
tree66c76e1b3c0f8bd290ab9fb68d58d3a212dfc58b /macosx/tkMacOSXWm.c
parented9cf42792f8332d1386414e459c9a4af9c66238 (diff)
parentb0ff53377869ccfb7928d389f7bd6fdeddaca3f3 (diff)
downloadtk-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.c96
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 {