summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorculler <culler>2019-02-02 19:13:17 (GMT)
committerculler <culler>2019-02-02 19:13:17 (GMT)
commit4f62ea993c2ba881bca1c4f8201bf261a6b52e3b (patch)
tree8025b02fc8294e7ac963366ce378b5ed7edcf0e2
parent6f9b782763a6e1605f10e734efa396ec738a04e0 (diff)
parent43b8641102c6727136926d0494328292a4c739aa (diff)
downloadtk-4f62ea993c2ba881bca1c4f8201bf261a6b52e3b.zip
tk-4f62ea993c2ba881bca1c4f8201bf261a6b52e3b.tar.gz
tk-4f62ea993c2ba881bca1c4f8201bf261a6b52e3b.tar.bz2
Add missing components of the implementation of transient windows on macOS.
-rw-r--r--macosx/tkMacOSXWm.c180
-rw-r--r--macosx/tkMacOSXWm.h14
2 files changed, 186 insertions, 8 deletions
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index a5e1564..6a6c254 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -322,6 +322,7 @@ static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr,
int *maxHeightPtr);
static void RemapWindows(TkWindow *winPtr,
MacDrawable *parentWin);
+static void RemoveTransient(TkWindow *winPtr);
#pragma mark NSWindow(TKWm)
@@ -681,6 +682,7 @@ TkWmNewWindow(
wmPtr->masterWindowName = NULL;
wmPtr->icon = NULL;
wmPtr->iconFor = NULL;
+ wmPtr->transientPtr = NULL;
wmPtr->sizeHintsFlags = 0;
wmPtr->minWidth = wmPtr->minHeight = 1;
wmPtr->maxWidth = 0;
@@ -882,10 +884,18 @@ TkWmDeadWindow(
TkWindow *winPtr) /* Top-level window that's being deleted. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
+ TkDisplay *dispPtr = TkGetDisplayList();
if (wmPtr == NULL) {
return;
}
+
+ /*
+ *If the dead window is a transient, remove it from the master's list.
+ */
+
+ RemoveTransient(winPtr);
+
Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
TopLevelEventProc, winPtr);
@@ -915,7 +925,6 @@ TkWmDeadWindow(
}
while (wmPtr->protPtr != NULL) {
ProtocolHandler *protPtr = wmPtr->protPtr;
-
wmPtr->protPtr = protPtr->nextPtr;
Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
}
@@ -930,6 +939,30 @@ TkWmDeadWindow(
}
/*
+ * If the dead window has a transient, remove references to it from
+ * the transient.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ Window master = TkGetTransientMaster(winPtr2);
+ TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master);
+ if (masterPtr == winPtr) {
+ wmPtr2 = winPtr2->wmInfoPtr;
+ wmPtr2->master = None;
+ ckfree(wmPtr2->masterWindowName);
+ wmPtr2->masterWindowName = NULL;
+ }
+ }
+
+ while (wmPtr->transientPtr != NULL) {
+ Transient *transientPtr = wmPtr->transientPtr;
+ wmPtr->transientPtr = transientPtr->nextPtr;
+ ckfree(transientPtr);
+ }
+
+ /*
* Delete the Mac window and remove it from the windowTable. The window
* could be nil if the window was never mapped. However, we don't do this
* for embedded windows, they don't go in the window list, and they do not
@@ -1758,6 +1791,7 @@ WmDeiconifyCmd(
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ TkDisplay *dispPtr = TkGetDisplayList();
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
@@ -1786,6 +1820,27 @@ WmDeiconifyCmd(
if (wmPtr->icon) {
Tk_UnmapWindow((Tk_Window)wmPtr->icon);
}
+
+ /*
+ * If this window has a transient, the transient must also be deiconified if
+ * it was withdrawn by the master.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
+ Window master = TkGetTransientMaster(winPtr2);
+ TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master);
+ if (masterPtr == winPtr) {
+ if (!(wmPtr2->hints.initial_state == WithdrawnState &&
+ (transientPtr->flags & WITHDRAWN_BY_MASTER) == 0)) {
+ TkpWmSetState(winPtr2, NormalState);
+ transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
+ }
+ }
+ }
+
return TCL_OK;
}
@@ -2272,6 +2327,7 @@ WmIconifyCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
+ TkDisplay *dispPtr = TkGetDisplayList();
register WmInfo *wmPtr = winPtr->wmInfoPtr;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
@@ -2308,6 +2364,24 @@ WmIconifyCmd(
if (wmPtr->icon) {
Tk_MapWindow((Tk_Window)wmPtr->icon);
}
+
+ /*
+ * If this window has a transient the transient must be withdrawn when
+ * the master is iconified.
+ */
+
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ Window master = TkGetTransientMaster(winPtr2);
+ TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master);
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
return TCL_OK;
}
@@ -3523,16 +3597,13 @@ WmTransientCmd(
return TCL_OK;
}
if (Tcl_GetString(objv[3])[0] == '\0') {
- wmPtr->master = None;
- if (wmPtr->masterWindowName != NULL) {
- ckfree(wmPtr->masterWindowName);
- }
- wmPtr->masterWindowName = NULL;
+ RemoveTransient(winPtr);
+
} else {
if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
return TCL_ERROR;
}
- TkWindow* masterPtr = (TkWindow*) master;
+ TkWindow *masterPtr = (TkWindow*) master;
while (!Tk_TopWinHierarchy(masterPtr)) {
/*
@@ -3568,6 +3639,27 @@ WmTransientCmd(
return TCL_ERROR;
}
+ /*
+ * Add the transient to the master's list.
+ */
+
+ Transient *transient = ckalloc(sizeof(Transient));
+ transient->winPtr = winPtr;
+ transient->flags = 0;
+ transient->nextPtr = wmPtr->transientPtr;
+ wmPtr2->transientPtr = transient;
+
+ /*
+ * If the master is withdrawn or iconic then withdraw the transient.
+ */
+
+ if ((wmPtr2->hints.initial_state == WithdrawnState ||
+ wmPtr2->hints.initial_state == IconicState) &&
+ wmPtr->hints.initial_state != WithdrawnState){
+ TkpWmSetState(winPtr, WithdrawnState);
+ transient->flags |= WITHDRAWN_BY_MASTER;
+ }
+
wmPtr->master = Tk_WindowId(masterPtr);
masterWindowName = masterPtr->pathName;
length = strlen(masterWindowName);
@@ -3580,6 +3672,61 @@ WmTransientCmd(
ApplyMasterOverrideChanges(winPtr, NULL);
return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RemoveTransient --
+ *
+ * Clears the transient's master record and removes the transient
+ * from the master's list.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * References to a master are removed from the transient's wmInfo
+ * structure and references to the transient are removed from its
+ * master's wmInfo.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RemoveTransient(
+ TkWindow *winPtr)
+{
+ WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
+ TkDisplay *dispPtr = TkGetDisplayList();
+ TkWindow *masterPtr;
+ if (wmPtr == NULL || wmPtr->master == None) {
+ return;
+ }
+ masterPtr = (TkWindow*)Tk_IdToWindow(dispPtr->display, wmPtr->master);
+ wmPtr2 = masterPtr->wmInfoPtr;
+ if (wmPtr2 == NULL) {
+ return;
+ }
+ wmPtr->master = None;
+ if (wmPtr->masterWindowName != NULL) {
+ ckfree(wmPtr->masterWindowName);
+ }
+ wmPtr->masterWindowName = NULL;
+ Transient *temp, *cursor = wmPtr2->transientPtr;
+ if (cursor->winPtr == winPtr) {
+ temp = cursor->nextPtr;
+ ckfree(cursor);
+ cursor = temp;
+ masterPtr->wmInfoPtr->transientPtr = cursor;
+ }
+ while (cursor != NULL) {
+ if (cursor->winPtr == winPtr) {
+ temp = cursor->nextPtr;
+ ckfree(cursor);
+ cursor = temp;
+ }
+ }
+}
/*
*----------------------------------------------------------------------
@@ -3620,11 +3767,29 @@ WmWithdrawCmd(
Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
return TCL_ERROR;
}
+
TkpWmSetState(winPtr, WithdrawnState);
+
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ TkDisplay *dispPtr = TkGetDisplayList();
[win orderOut:nil];
[win setExcludedFromWindowsMenu:YES];
+ /*
+ * If this window has a transient, the transient must also be withdrawn.
+ */
+ for (Transient *transientPtr = wmPtr->transientPtr;
+ transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
+ TkWindow *winPtr2 = transientPtr->winPtr;
+ Window master = TkGetTransientMaster(winPtr2);
+ TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master);
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
return TCL_OK;
}
@@ -4734,7 +4899,6 @@ Tk_MoveToplevelWindow(
wmPtr->x = x;
wmPtr->y = y;
wmPtr->flags |= WM_MOVE_PENDING;
- // wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {
wmPtr->sizeHintsFlags |= USPosition;
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h
index 43f1a7a..a7ea92c 100644
--- a/macosx/tkMacOSXWm.h
+++ b/macosx/tkMacOSXWm.h
@@ -36,6 +36,17 @@ typedef struct ProtocolHandler {
* THE LAST FIELD OF THE STRUCTURE. */
} ProtocolHandler;
+/* The following data structure is used in the TkWmInfo to maintain a list of all of the
+ * transient windows belonging to a given master.
+ */
+
+typedef struct Transient {
+ TkWindow *winPtr;
+ int flags;
+ struct Transient *nextPtr;
+} Transient;
+
+#define WITHDRAWN_BY_MASTER 0x1
/*
* A data structure of the following type holds window-manager-related
@@ -70,6 +81,9 @@ typedef struct TkWmInfo {
* NULL. */
Tk_Window iconFor; /* Window for which this window is icon, or
* NULL if this isn't an icon for anyone. */
+ Transient *transientPtr; /* First item in a list of all transient windows
+ * belonging to this window, or NULL if there
+ * are no transients. */
/*
* Information used to construct an XSizeHints structure for the window