summaryrefslogtreecommitdiffstats
path: root/macosx
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
parented9cf42792f8332d1386414e459c9a4af9c66238 (diff)
parentb0ff53377869ccfb7928d389f7bd6fdeddaca3f3 (diff)
downloadtk-48f3771a552ad6c5f6f07b86545757a2f92ba633.zip
tk-48f3771a552ad6c5f6f07b86545757a2f92ba633.tar.gz
tk-48f3771a552ad6c5f6f07b86545757a2f92ba633.tar.bz2
Fix aqua MapNotify and UnmapNotify
Diffstat (limited to 'macosx')
-rw-r--r--macosx/tkMacOSXPort.h8
-rw-r--r--macosx/tkMacOSXSubwindows.c78
-rw-r--r--macosx/tkMacOSXWindowEvent.c3
-rw-r--r--macosx/tkMacOSXWm.c96
4 files changed, 125 insertions, 60 deletions
diff --git a/macosx/tkMacOSXPort.h b/macosx/tkMacOSXPort.h
index ab0fadc..61c0d0d 100644
--- a/macosx/tkMacOSXPort.h
+++ b/macosx/tkMacOSXPort.h
@@ -149,4 +149,12 @@ MODULE_SCOPE unsigned long TkMacOSXRGBPixel(unsigned long red, unsigned long gre
unsigned long blue);
#define TkpGetPixel(p) (TkMacOSXRGBPixel(p->red >> 8, p->green >> 8, p->blue >> 8))
+/*
+ * Used by tkWindow.c
+ */
+
+MODULE_SCOPE void TkMacOSXHandleMapOrUnmap(Tk_Window tkwin, XEvent *event);
+
+#define TkpHandleMapOrUnmap(tkwin, event) TkMacOSXHandleMapOrUnmap(tkwin, event)
+
#endif /* _TKMACPORT */
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 9309b67..a358bde 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -119,14 +119,18 @@ XDestroyWindow(
*
* XMapWindow --
*
- * Map the given X Window to the screen. See X window documentation for
- * more details.
+ * This X11 stub maps the given X11 Window but does not update any of
+ * the Tk structures describing the window. Tk applications should
+ * never call this directly, but it is called by Tk_MapWindow and
+ * Tk_WmMapWindow.
*
* Results:
- * None.
+ * Returns Success or BadWindow.
*
* Side effects:
- * The subwindow or toplevel may appear on the screen.
+ * The subwindow or toplevel may appear on the screen. VisibilityNotify
+ * events are generated.
+ *
*
*----------------------------------------------------------------------
*/
@@ -142,7 +146,6 @@ XMapWindow(
MacDrawable *macWin = (MacDrawable *)window;
TkWindow *winPtr = macWin->winPtr;
NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
- XEvent event;
static Bool initialized = NO;
/*
@@ -158,7 +161,6 @@ XMapWindow(
}
display->request++;
- winPtr->flags |= TK_MAPPED;
if (Tk_IsTopLevel(winPtr)) {
if (!Tk_IsEmbedded(winPtr)) {
TKContentView *view = [win contentView];
@@ -193,30 +195,7 @@ XMapWindow(
TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
}
-
TkMacOSXInvalClipRgns((Tk_Window)winPtr);
-
- /*
- * We only need to send the MapNotify event for toplevel windows.
- */
-
- event.xany.serial = LastKnownRequestProcessed(display);
- event.xany.send_event = False;
- event.xany.display = display;
-
- event.xmap.window = window;
- event.xmap.type = MapNotify;
- event.xmap.event = window;
- event.xmap.override_redirect = winPtr->atts.override_redirect;
-
- /*
- * To update the mapped status of packed or placed subwindows
- * we handle this event immediately and then process the idle
- * events that it generates.
- */
-
- Tk_HandleEvent(&event);
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
} else {
/*
@@ -227,6 +206,11 @@ XMapWindow(
TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);
}
+ /*
+ * Mark the toplevel as needing to be redrawn, unless the window is being
+ * mapped while drawing is taking place.
+ */
+
TKContentView *view = [win contentView];
if (view != [NSView focusView]) {
[view addTkDirtyRect:[view bounds]];
@@ -237,6 +221,7 @@ XMapWindow(
*/
if (initialized) {
+ XEvent event;
event.xany.send_event = False;
event.xany.display = display;
event.xvisibility.type = VisibilityNotify;
@@ -287,11 +272,13 @@ NotifyVisibility(
*
* XUnmapWindow --
*
- * Unmap the given X Window to the screen. See X window documentation for
- * more details.
+ * This X11 stub maps the given X11 Window but does not update any of
+ * The Tk structures describing the window. Tk applications should
+ * never call this directly, but it is called by Tk_UnmapWindow and
+ * Tk_WmUnmapWindow.
*
* Results:
- * None.
+ * Always returns Success or BadWindow.
*
* Side effects:
* The subwindow or toplevel may be removed from the screen.
@@ -308,8 +295,10 @@ XUnmapWindow(
TkWindow *winPtr = macWin->winPtr;
TkWindow *parentPtr = winPtr->parentPtr;
NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
- XEvent event;
+ if (!window) {
+ return BadWindow;
+ }
display->request++;
if (Tk_IsTopLevel(winPtr)) {
if (!Tk_IsEmbedded(winPtr) &&
@@ -318,28 +307,6 @@ XUnmapWindow(
[win setExcludedFromWindowsMenu:YES];
}
TkMacOSXInvalClipRgns((Tk_Window)winPtr);
-
- /*
- * We only need to send the UnmapNotify event for toplevel windows.
- */
-
- event.xany.serial = LastKnownRequestProcessed(display);
- event.xany.send_event = False;
- event.xany.display = display;
-
- event.xunmap.type = UnmapNotify;
- event.xunmap.window = window;
- event.xunmap.event = window;
- event.xunmap.from_configure = false;
-
- /*
- * To update the mapped status of packed or placed subwindows
- * we handle this event immediately and then process the idle
- * events that it generates.
- */
-
- Tk_HandleEvent(&event);
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
} else {
/*
* Rebuild the visRgn clip region for the parent so it will be allowed
@@ -355,7 +322,6 @@ XUnmapWindow(
TkMacOSXInvalClipRgns((Tk_Window)parentPtr);
TkMacOSXUpdateClipRgn(parentPtr);
}
- winPtr->flags &= ~TK_MAPPED;
TKContentView *view = [win contentView];
if (view != [NSView focusView]) {
[view addTkDirtyRect:[view bounds]];
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 0a8d363..98bec7d 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -1086,7 +1086,7 @@ ConfigureRestrictProc(
}
/*
- * In macOS 10.14 and later his method is called when a user changes between
+ * In macOS 10.14 and later this method is called when a user changes between
* light and dark mode or changes the accent color. The implementation
* generates two virtual events. The first is either <<LightAqua>> or
* <<DarkAqua>>, depending on the view's current effective appearance. The
@@ -1134,6 +1134,7 @@ static const char *const accentNames[] = {
}
if (!defaultColor) {
defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor";
+ preferences = [[NSUserDefaults standardUserDefaults] retain];
/*
* AppKit calls this method when the user changes the Accent Color
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 {