summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/menu.n21
-rw-r--r--doc/ttk_treeview.n3
-rw-r--r--doc/wm.n29
-rw-r--r--generic/tkCanvPoly.c2
-rw-r--r--generic/tkFocus.c70
-rw-r--r--generic/tkImgGIF.c21
-rw-r--r--generic/tkInt.decls2
-rw-r--r--generic/tkIntPlatDecls.h4
-rw-r--r--generic/tkMain.c35
-rw-r--r--generic/tkMenu.c25
-rw-r--r--generic/tkMenu.h6
-rw-r--r--generic/tkMenuDraw.c64
-rw-r--r--generic/tkPlace.c6
-rw-r--r--generic/tkRectOval.c3
-rw-r--r--generic/tkScale.c43
-rw-r--r--generic/tkScale.h3
-rw-r--r--generic/tkSelect.c2
-rw-r--r--generic/tkSquare.c2
-rw-r--r--library/bgerror.tcl17
-rw-r--r--library/demos/puzzle.tcl2
-rw-r--r--library/menu.tcl248
-rw-r--r--library/ttk/altTheme.tcl2
-rw-r--r--library/ttk/aquaTheme.tcl2
-rw-r--r--library/ttk/clamTheme.tcl2
-rw-r--r--library/ttk/classicTheme.tcl2
-rw-r--r--library/ttk/defaults.tcl2
-rw-r--r--library/ttk/vistaTheme.tcl2
-rw-r--r--library/ttk/winTheme.tcl2
-rw-r--r--library/ttk/xpTheme.tcl2
-rw-r--r--macosx/tkMacOSXButton.c148
-rw-r--r--macosx/tkMacOSXDefault.h8
-rw-r--r--macosx/tkMacOSXEmbed.c148
-rw-r--r--macosx/tkMacOSXEvent.c38
-rw-r--r--macosx/tkMacOSXInit.c10
-rw-r--r--macosx/tkMacOSXKeyEvent.c56
-rw-r--r--macosx/tkMacOSXMenu.c278
-rw-r--r--macosx/tkMacOSXMenubutton.c246
-rw-r--r--macosx/tkMacOSXMouseEvent.c166
-rw-r--r--macosx/tkMacOSXSend.c2
-rw-r--r--macosx/tkMacOSXSubwindows.c26
-rw-r--r--macosx/tkMacOSXWindowEvent.c23
-rw-r--r--macosx/tkMacOSXWm.c283
-rw-r--r--macosx/tkMacOSXWm.h20
-rw-r--r--tests/imgPhoto.test33
-rw-r--r--tests/menu.test2
-rw-r--r--tests/menubut.test26
-rw-r--r--tests/scale.test59
-rw-r--r--tests/send.test18
-rw-r--r--tests/text.test15
-rw-r--r--tests/unixButton.test24
-rw-r--r--tests/unixEmbed.test648
-rw-r--r--tests/unixWm.test39
-rw-r--r--tests/wm.test14
-rw-r--r--unix/tkUnixEmbed.c32
-rw-r--r--unix/tkUnixMenu.c111
-rw-r--r--unix/tkUnixScale.c8
-rw-r--r--unix/tkUnixWm.c20
-rw-r--r--win/makefile.vc8
-rw-r--r--win/tkWinClipboard.c12
-rw-r--r--win/tkWinDialog.c7
-rw-r--r--win/tkWinEmbed.c9
-rw-r--r--win/tkWinInit.c2
-rw-r--r--win/tkWinKey.c2
-rw-r--r--win/tkWinMenu.c130
-rw-r--r--win/tkWinWm.c20
-rw-r--r--win/ttkWinXPTheme.c53
66 files changed, 2296 insertions, 1072 deletions
diff --git a/doc/menu.n b/doc/menu.n
index ac60e65..338ce6a 100644
--- a/doc/menu.n
+++ b/doc/menu.n
@@ -470,18 +470,19 @@ a menu entry does not automatically unpost the menu; the default
bindings normally take care of this before invoking the \fBinvoke\fR
widget command.
.TP
-\fIpathName \fBpost \fIx y\fR
+\fIpathName \fBpost \fIx y\fR ?\fIindex\fR?
.
Arrange for the menu to be displayed on the screen at the root-window
-coordinates given by \fIx\fR and \fIy\fR. These coordinates are
-adjusted if necessary to guarantee that the entire menu is visible on
-the screen. This command normally returns an empty string.
-If the \fB\-postcommand\fR option has been specified, then its value is
-executed as a Tcl script before posting the menu and the result of
-that script is returned as the result of the \fBpost\fR widget
-command.
-If an error returns while executing the command, then the error is
-returned without posting the menu.
+coordinates given by \fIx\fR and \fIy\fR. If an index is specified
+the menu will be located so that the entry with that index is
+displayed at the point. These coordinates are adjusted if necessary to
+guarantee that the entire menu is visible on the screen. This command
+normally returns an empty string. If the \fB\-postcommand\fR option
+has been specified, then its value is executed as a Tcl script before
+posting the menu and the result of that script is returned as the
+result of the \fBpost\fR widget command. If an error returns while
+executing the command, then the error is returned without posting the
+menu.
.TP
\fIpathName \fBpostcascade \fIindex\fR
.
diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n
index b81bc62..96565a3 100644
--- a/doc/ttk_treeview.n
+++ b/doc/ttk_treeview.n
@@ -434,6 +434,9 @@ Specifies the font to use when drawing text.
Specifies the item image, in case the item's \fB\-image\fR option is empty.
.\" .PP
.\" \fI(@@@ TODO: sort out order of precedence for options)\fR
+.PP
+Tag priority is decided by the creation order: tags created first receive
+higher priority.
.SH "COLUMN IDENTIFIERS"
.PP
Column identifiers take any of the following forms:
diff --git a/doc/wm.n b/doc/wm.n
index e7aedf7..a137d06 100644
--- a/doc/wm.n
+++ b/doc/wm.n
@@ -710,20 +710,21 @@ specified then the command returns the current title for the
.TP
\fBwm transient \fIwindow\fR ?\fImaster\fR?
.
-If \fImaster\fR is specified, then the window manager is informed
-that \fIwindow\fR is a transient window (e.g. pull-down menu) working
-on behalf of \fImaster\fR (where \fImaster\fR is the
-path name for a top-level window). If \fImaster\fR
-is specified as an empty string then \fIwindow\fR is marked as not
-being a transient window any more. Otherwise the command
-returns the path name of \fIwindow\fR's current master, or an
-empty string if \fIwindow\fR is not currently a transient window.
-A transient window will mirror state changes in the master and
-inherit the state of the master when initially mapped. It is an
-error to attempt to make a window a transient of itself.
-The window manager may also decorate a transient window differently, removing
-some features normally present (e.g., minimize and maximize buttons) though
-this is entirely at the discretion of the window manager.
+If \fImaster\fR is specified, then the window manager is informed that
+\fIwindow\fR is a transient window (e.g. pull-down menu) working on
+behalf of \fImaster\fR (where \fImaster\fR is the path name for a
+top-level window). If \fImaster\fR is specified as an empty string
+then \fIwindow\fR is marked as not being a transient window any more.
+Otherwise the command returns the path name of \fIwindow\fR's current
+master, or an empty string if \fIwindow\fR is not currently a
+transient window. A transient window will mirror state changes in the
+master and inherit the state of the master when initially mapped. The
+directed graph with an edge from each transient to its master must be
+acyclic. In particular, it is an error to attempt to make a window a
+transient of itself. The window manager may also decorate a transient
+window differently, removing some features normally present (e.g.,
+minimize and maximize buttons) though this is entirely at the
+discretion of the window manager.
.TP
\fBwm withdraw \fIwindow\fR
.
diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c
index be80378..6a8f865 100644
--- a/generic/tkCanvPoly.c
+++ b/generic/tkCanvPoly.c
@@ -518,7 +518,7 @@ ConfigurePolygon(
* Mac OS X CG drawing needs access to the outline linewidth
* even for fills (as linewidth controls antialiasing).
*/
- gcValues.line_width = polyPtr->outline.gc != None ?
+ gcValues.line_width = polyPtr->outline.gc != NULL ?
polyPtr->outline.gc->line_width : 0;
mask |= GCLineWidth;
#endif
diff --git a/generic/tkFocus.c b/generic/tkFocus.c
index cb9c4ab..7a4bdbc 100644
--- a/generic/tkFocus.c
+++ b/generic/tkFocus.c
@@ -551,12 +551,17 @@ TkSetFocusWin(
return;
}
+ /*
+ * Get the current focus window with the same display and application
+ * as winPtr.
+ */
+
displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
/*
- * If force is set, we should make sure we grab the focus regardless of
- * the current focus window since under Windows, we may need to take
- * control away from another application.
+ * Do nothing if the window already has focus and force is not set. If
+ * force is set, we need to grab the focus, since under Windows or macOS
+ * this may involve taking control away from another application.
*/
if (winPtr == displayFocusPtr->focusWinPtr && !force) {
@@ -564,14 +569,15 @@ TkSetFocusWin(
}
/*
- * Find the top-level window for winPtr, then find (or create) a record
- * for the top-level. Also see whether winPtr and all its ancestors are
+ * Find the toplevel window for winPtr, then find (or create) a record
+ * for the toplevel. Also see whether winPtr and all its ancestors are
* mapped.
*/
allMapped = 1;
for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) {
if (topLevelPtr == NULL) {
+
/*
* The window is being deleted. No point in worrying about giving
* it the focus.
@@ -588,11 +594,11 @@ TkSetFocusWin(
}
/*
- * If the new focus window isn't mapped, then we can't focus on it (X will
- * generate an error, for example). Instead, create an event handler that
- * will set the focus to this window once it gets mapped. At the same
- * time, delete any old handler that might be around; it's no longer
- * relevant.
+ * If any ancestor of the new focus window isn't mapped, then we can't set
+ * focus for it (X will generate an error, for example). Instead, create
+ * an event handler that will set the focus to this window once it gets
+ * mapped. At the same time, delete any old handler that might be around;
+ * it's no longer relevant.
*/
if (displayFocusPtr->focusOnMapPtr != NULL) {
@@ -623,28 +629,36 @@ TkSetFocusWin(
}
tlFocusPtr->focusWinPtr = winPtr;
- /*
- * Reset the window system's focus window and generate focus events, with
- * two special cases:
- *
- * 1. If the application is embedded and doesn't currently have the focus,
- * don't set the focus directly. Instead, see if the embedding code can
- * claim the focus from the enclosing container.
- * 2. Otherwise, if the application doesn't currently have the focus,
- * don't change the window system's focus unless it was already in this
- * application or "force" was specified.
- */
+ if (topLevelPtr->flags & TK_EMBEDDED) {
+
+ /*
+ * We are assigning focus to an embedded toplevel. The platform
+ * specific function TkpClaimFocus needs to handle the job of
+ * assigning focus to the container, since we have no way to find the
+ * contaiuner.
+ */
- if ((topLevelPtr->flags & TK_EMBEDDED)
- && (displayFocusPtr->focusWinPtr == NULL)) {
TkpClaimFocus(topLevelPtr, force);
} else if ((displayFocusPtr->focusWinPtr != NULL) || force) {
+
+ /*
+ * If we are forcing removal of focus from a container hosting a
+ * toplevel from a different application, clear the focus in that
+ * application.
+ */
+
+ if (force) {
+ TkWindow *focusPtr = winPtr->dispPtr->focusPtr;
+ if (focusPtr && focusPtr->mainPtr != winPtr->mainPtr) {
+ DisplayFocusInfo *displayFocusPtr2 = FindDisplayFocusInfo(
+ focusPtr->mainPtr, focusPtr->dispPtr);
+ displayFocusPtr2->focusWinPtr = NULL;
+ }
+ }
+
/*
- * Generate events to shift focus between Tk windows. We do this
- * regardless of what TkpChangeFocus does with the real X focus so
- * that Tk widgets track focus commands when there is no window
- * manager. GenerateFocusEvents will set up a serial number marker so
- * we discard focus events that are triggered by the ChangeFocus.
+ * Call the platform specific function TkpChangeFocus to move the
+ * window manager's focus to a new toplevel.
*/
serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c
index 7c4872b..0c32047 100644
--- a/generic/tkImgGIF.c
+++ b/generic/tkImgGIF.c
@@ -1034,7 +1034,7 @@ ReadImage(
int transparent)
{
unsigned char initialCodeSize;
- int xpos = 0, ypos = 0, pass = 0, i;
+ int xpos = 0, ypos = 0, pass = 0, i, count;
register unsigned char *pixelPtr;
static const int interlaceStep[] = { 8, 8, 4, 2 };
static const int interlaceStart[] = { 0, 4, 2, 1 };
@@ -1252,6 +1252,25 @@ ReadImage(
}
pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);
}
+
+ /*
+ * Now read until the final zero byte.
+ * It was observed that there might be 1 length blocks
+ * (test imgPhoto-14.1) which are not read.
+ *
+ * The field "stack" is abused for temporary buffer. it has 4096 bytes
+ * and we need 256.
+ *
+ * Loop until we hit a 0 length block which is the end sign.
+ */
+ while ( 0 < (count = GetDataBlock(gifConfPtr, chan, stack)))
+ {
+ if (-1 == count ) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "error reading GIF image: %s", Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+ }
return TCL_OK;
}
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index d0b7678..a3e1f98 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -1009,7 +1009,7 @@ declare 47 aqua {
Tk_Window TkMacOSXGetCapture(void)
}
declare 49 aqua {
- Window TkGetTransientMaster(TkWindow *winPtr)
+ Tk_Window TkGetTransientMaster(TkWindow *winPtr)
}
declare 50 aqua {
int TkGenerateButtonEvent(int x, int y, Window window, unsigned int state)
diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h
index ded5ac5..26a5f46 100644
--- a/generic/tkIntPlatDecls.h
+++ b/generic/tkIntPlatDecls.h
@@ -243,7 +243,7 @@ EXTERN int TkpIsWindowFloating(void *window);
EXTERN Tk_Window TkMacOSXGetCapture(void);
/* Slot 48 is reserved */
/* 49 */
-EXTERN Window TkGetTransientMaster(TkWindow *winPtr);
+EXTERN Tk_Window TkGetTransientMaster(TkWindow *winPtr);
/* 50 */
EXTERN int TkGenerateButtonEvent(int x, int y, Window window,
unsigned int state);
@@ -392,7 +392,7 @@ typedef struct TkIntPlatStubs {
int (*tkpIsWindowFloating) (void *window); /* 46 */
Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */
void (*reserved48)(void);
- Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
+ Tk_Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */
int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */
void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */
void (*tkMacOSXSetDrawingEnabled) (TkWindow *winPtr, int flag); /* 52 */
diff --git a/generic/tkMain.c b/generic/tkMain.c
index a7d4ca1..b80ce4d 100644
--- a/generic/tkMain.c
+++ b/generic/tkMain.c
@@ -79,22 +79,31 @@ extern const TclIntPlatStubs *tclIntPlatStubsPtr;
#endif
/*
- * Further on, in UNICODE mode, we need to use Tcl_NewUnicodeObj,
- * while otherwise NewNativeObj is needed (which provides proper
- * conversion from native encoding to UTF-8).
+ * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise
+ * NewNativeObj is needed (which provides proper conversion from native
+ * encoding to UTF-8).
*/
+
+static inline Tcl_Obj *
+NewNativeObj(
+ TCHAR *string,
+ int length)
+{
+ Tcl_Obj *obj;
+ Tcl_DString ds;
+
#ifdef UNICODE
-# define NewNativeObj Tcl_NewUnicodeObj
-#else /* !UNICODE */
- static Tcl_Obj *NewNativeObj(char *string, int length) {
- Tcl_Obj *obj;
- Tcl_DString ds;
- Tcl_ExternalToUtfDString(NULL, string, length, &ds);
- obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
- Tcl_DStringFree(&ds);
- return obj;
+ if (length > 0) {
+ length *= sizeof(WCHAR);
+ }
+ Tcl_WinTCharToUtf(string, length, &ds);
+#else
+ Tcl_ExternalToUtfDString(NULL, (char *) string, length, &ds);
+#endif
+ obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
+ Tcl_DStringFree(&ds);
+ return obj;
}
-#endif /* !UNICODE */
/*
* Declarations for various library functions and variables (don't want to
diff --git a/generic/tkMenu.c b/generic/tkMenu.c
index a31666d..38e3bbd 100644
--- a/generic/tkMenu.c
+++ b/generic/tkMenu.c
@@ -870,32 +870,37 @@ MenuWidgetObjCmd(
break;
}
case MENU_POST: {
- int x, y;
+ int x, y, index = -1;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ if (objc != 4 && objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y ?index?");
goto error;
}
if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
|| (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
goto error;
}
+ if (objc == 5) {
+ if (TkGetMenuIndex(interp, menuPtr, objv[4], 0, &index) != TCL_OK) {
+ goto error;
+ }
+ }
/*
- * Tearoff menus are posted differently on Mac and Windows than
- * non-tearoffs. TkpPostMenu does not actually map the menu's window
- * on those platforms, and popup menus have to be handled specially.
- * Also, menubar menues are not intended to be posted (bug 1567681,
- * 2160206).
+ * Tearoff menus are the same as ordinary menus on the Mac and are
+ * posted differently on Windows than non-tearoffs. TkpPostMenu
+ * does not actually map the menu's window on those platforms, and
+ * popup menus have to be handled specially. Also, menubar menus are
+ * not intended to be posted (bug 1567681, 2160206).
*/
if (menuPtr->menuType == MENUBAR) {
Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL);
return TCL_ERROR;
} else if (menuPtr->menuType != TEAROFF_MENU) {
- result = TkpPostMenu(interp, menuPtr, x, y);
+ result = TkpPostMenu(interp, menuPtr, x, y, index);
} else {
- result = TkPostTearoffMenu(interp, menuPtr, x, y);
+ result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);
}
break;
}
diff --git a/generic/tkMenu.h b/generic/tkMenu.h
index 9522db2..4cc3d1b 100644
--- a/generic/tkMenu.h
+++ b/generic/tkMenu.h
@@ -520,7 +520,7 @@ MODULE_SCOPE int TkPostCommand(TkMenu *menuPtr);
MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr,
TkMenuEntry *mePtr);
MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
- int x, int y);
+ int x, int y);
MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr);
MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr);
@@ -543,7 +543,9 @@ MODULE_SCOPE void TkpMenuInit(void);
MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr);
MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr);
MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr,
- int x, int y);
+ int x, int y, int index);
+MODULE_SCOPE int TkpPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr,
+ int x, int y, int index);
MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr);
#endif /* _TKMENU */
diff --git a/generic/tkMenuDraw.c b/generic/tkMenuDraw.c
index 3abfc3c..bd00d38 100644
--- a/generic/tkMenuDraw.c
+++ b/generic/tkMenuDraw.c
@@ -807,9 +807,8 @@ TkMenuImageProc(
*
* TkPostTearoffMenu --
*
- * Posts a menu on the screen. Used to post tearoff menus. On Unix, all
- * menus are posted this way. Adjusts the menu's position so that it fits
- * on the screen, and maps and raises the menu.
+ * Posts a tearoff menu on the screen. Adjusts the menu's position so
+ * that it fits on the screen, and maps and raises the menu.
*
* Results:
* Returns a standard Tcl Error.
@@ -827,64 +826,7 @@ TkPostTearoffMenu(
int x, int y) /* The root X,Y coordinates where we are
* posting */
{
- int vRootX, vRootY, vRootWidth, vRootHeight;
- int result;
-
- TkActivateMenuEntry(menuPtr, -1);
- TkRecomputeMenu(menuPtr);
- result = TkPostCommand(menuPtr);
- if (result != TCL_OK) {
- return result;
- }
-
- /*
- * The post commands could have deleted the menu, which means we are dead
- * and should go away.
- */
-
- if (menuPtr->tkwin == NULL) {
- return TCL_OK;
- }
-
- /*
- * Adjust the position of the menu if necessary to keep it visible on the
- * screen. There are two special tricks to make this work right:
- *
- * 1. If a virtual root window manager is being used then the coordinates
- * are in the virtual root window of menuPtr's parent; since the menu
- * uses override-redirect mode it will be in the *real* root window for
- * the screen, so we have to map the coordinates from the virtual root
- * (if any) to the real root. Can't get the virtual root from the menu
- * itself (it will never be seen by the wm) so use its parent instead
- * (it would be better to have an an option that names a window to use
- * for this...).
- * 2. The menu may not have been mapped yet, so its current size might be
- * the default 1x1. To compute how much space it needs, use its
- * requested size, not its actual size.
- */
-
- Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
- &vRootWidth, &vRootHeight);
- vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
- if (x > vRootX + vRootWidth) {
- x = vRootX + vRootWidth;
- }
- if (x < vRootX) {
- x = vRootX;
- }
- vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
- if (y > vRootY + vRootHeight) {
- y = vRootY + vRootHeight;
- }
- if (y < vRootY) {
- y = vRootY;
- }
- Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
- if (!Tk_IsMapped(menuPtr->tkwin)) {
- Tk_MapWindow(menuPtr->tkwin);
- }
- TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
- return TCL_OK;
+ return TkpPostTearoffMenu(interp, menuPtr, x, y, -1);
}
/*
diff --git a/generic/tkPlace.c b/generic/tkPlace.c
index 2c06977..8eee5a1 100644
--- a/generic/tkPlace.c
+++ b/generic/tkPlace.c
@@ -1185,6 +1185,12 @@ PlaceRequestProc(
if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
&& (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {
+ /*
+ * Send a ConfigureNotify to indicate that the size change
+ * request was rejected.
+ */
+
+ TkDoConfigureNotify((TkWindow *)(slavePtr->tkwin));
return;
}
masterPtr = slavePtr->masterPtr;
diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c
index daae092..359d3ef 100644
--- a/generic/tkRectOval.c
+++ b/generic/tkRectOval.c
@@ -515,8 +515,7 @@ ConfigureRectOval(
* Mac OS X CG drawing needs access to the outline linewidth even for
* fills (as linewidth controls antialiasing).
*/
-
- gcValues.line_width = rectOvalPtr->outline.gc != None ?
+ gcValues.line_width = rectOvalPtr->outline.gc != NULL ?
rectOvalPtr->outline.gc->line_width : 0;
mask |= GCLineWidth;
#endif
diff --git a/generic/tkScale.c b/generic/tkScale.c
index 6f61046..29f8722 100644
--- a/generic/tkScale.c
+++ b/generic/tkScale.c
@@ -611,7 +611,7 @@ ConfigureScale(
TCL_GLOBAL_ONLY);
if ((valuePtr != NULL) &&
(Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
- scalePtr->value = TkRoundToResolution(scalePtr, value);
+ scalePtr->value = TkRoundValueToResolution(scalePtr, value);
}
}
@@ -620,10 +620,10 @@ ConfigureScale(
* orientation and creating GCs.
*/
- scalePtr->fromValue = TkRoundToResolution(scalePtr,
+ scalePtr->fromValue = TkRoundValueToResolution(scalePtr,
scalePtr->fromValue);
- scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
- scalePtr->tickInterval = TkRoundToResolution(scalePtr,
+ scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);
+ scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,
scalePtr->tickInterval);
/*
@@ -1119,10 +1119,14 @@ TkEventuallyRedrawScale(
/*
*--------------------------------------------------------------
*
- * TkRoundToResolution --
+ * TkRoundValueToResolution, TkRoundIntervalToResolution --
*
* Round a given floating-point value to the nearest multiple of the
* scale's resolution.
+ * TkRoundValueToResolution rounds an absolute value based on the from
+ * value as a reference.
+ * TkRoundIntervalToResolution rounds a relative value without
+ * reference, i.e. it rounds an interval.
*
* Results:
* The return value is the rounded result.
@@ -1134,7 +1138,16 @@ TkEventuallyRedrawScale(
*/
double
-TkRoundToResolution(
+TkRoundValueToResolution(
+ TkScale *scalePtr, /* Information about scale widget. */
+ double value) /* Value to round. */
+{
+ return TkRoundIntervalToResolution(scalePtr, value - scalePtr->fromValue)
+ + scalePtr->fromValue;
+}
+
+double
+TkRoundIntervalToResolution(
TkScale *scalePtr, /* Information about scale widget. */
double value) /* Value to round. */
{
@@ -1147,13 +1160,13 @@ TkRoundToResolution(
rounded = scalePtr->resolution * tick;
rem = value - rounded;
if (rem < 0) {
- if (rem <= -scalePtr->resolution/2) {
- rounded = (tick - 1.0) * scalePtr->resolution;
- }
+ if (rem <= -scalePtr->resolution/2) {
+ rounded = (tick - 1.0) * scalePtr->resolution;
+ }
} else {
- if (rem >= scalePtr->resolution/2) {
- rounded = (tick + 1.0) * scalePtr->resolution;
- }
+ if (rem >= scalePtr->resolution/2) {
+ rounded = (tick + 1.0) * scalePtr->resolution;
+ }
}
return rounded;
}
@@ -1238,7 +1251,7 @@ ScaleVarProc(
resultStr = "can't assign non-numeric value to scale variable";
ScaleSetVariable(scalePtr);
} else {
- scalePtr->value = TkRoundToResolution(scalePtr, value);
+ scalePtr->value = TkRoundValueToResolution(scalePtr, value);
/*
* This code is a bit tricky because it sets the scale's value before
@@ -1282,7 +1295,7 @@ TkScaleSetValue(
int invokeCommand) /* Non-zero means invoked -command option to
* notify of new value, 0 means don't. */
{
- value = TkRoundToResolution(scalePtr, value);
+ value = TkRoundValueToResolution(scalePtr, value);
if ((value < scalePtr->fromValue)
^ (scalePtr->toValue < scalePtr->fromValue)) {
value = scalePtr->fromValue;
@@ -1402,7 +1415,7 @@ TkScalePixelToValue(
}
value = scalePtr->fromValue +
value * (scalePtr->toValue - scalePtr->fromValue);
- return TkRoundToResolution(scalePtr, value);
+ return TkRoundValueToResolution(scalePtr, value);
}
/*
diff --git a/generic/tkScale.h b/generic/tkScale.h
index 4f28738..d44e65b 100644
--- a/generic/tkScale.h
+++ b/generic/tkScale.h
@@ -219,7 +219,8 @@ typedef struct TkScale {
*/
MODULE_SCOPE void TkEventuallyRedrawScale(TkScale *scalePtr, int what);
-MODULE_SCOPE double TkRoundToResolution(TkScale *scalePtr, double value);
+MODULE_SCOPE double TkRoundValueToResolution(TkScale *scalePtr, double value);
+MODULE_SCOPE double TkRoundIntervalToResolution(TkScale *scalePtr, double value);
MODULE_SCOPE TkScale * TkpCreateScale(Tk_Window tkwin);
MODULE_SCOPE void TkpDestroyScale(TkScale *scalePtr);
MODULE_SCOPE void TkpDisplayScale(ClientData clientData);
diff --git a/generic/tkSelect.c b/generic/tkSelect.c
index fcfd323..8ba0c5f 100644
--- a/generic/tkSelect.c
+++ b/generic/tkSelect.c
@@ -26,7 +26,7 @@ typedef struct {
int charOffset; /* The offset of the next char to retrieve. */
int byteOffset; /* The expected byte offset of the next
* chunk. */
- char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character
+ char buffer[4]; /* A buffer to hold part of a UTF character
* that is split across chunks. */
char command[1]; /* Command to invoke. Actual space is
* allocated as large as necessary. This must
diff --git a/generic/tkSquare.c b/generic/tkSquare.c
index 40d5e8f..e92c03c 100644
--- a/generic/tkSquare.c
+++ b/generic/tkSquare.c
@@ -335,7 +335,7 @@ SquareConfigure(
Tk_SetWindowBackground(squarePtr->tkwin,
Tk_3DBorderColor(bgBorder)->pixel);
Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
- if ((squarePtr->gc == NULL) && (doubleBuffer)) {
+ if ((squarePtr->gc == NULL) && doubleBuffer) {
XGCValues gcValues;
gcValues.function = GXcopy;
gcValues.graphics_exposures = False;
diff --git a/library/bgerror.tcl b/library/bgerror.tcl
index b15387e..574ad8b 100644
--- a/library/bgerror.tcl
+++ b/library/bgerror.tcl
@@ -97,7 +97,7 @@ proc ::tk::dialog::error::ReturnInDetails w {
# Arguments:
# err - The error message.
#
-proc ::tk::dialog::error::bgerror err {
+proc ::tk::dialog::error::bgerror {err {flag 1}} {
global errorInfo
variable button
@@ -106,15 +106,20 @@ proc ::tk::dialog::error::bgerror err {
set ret [catch {::tkerror $err} msg];
if {$ret != 1} {return -code $ret $msg}
- # Ok the application's tkerror either failed or was not found
- # we use the default dialog then :
+ # The application's tkerror either failed or was not found
+ # so we use the default dialog. But on Aqua we cannot display
+ # the dialog if the background error occurs in an idle task
+ # being processed inside of [NSView drawRect]. In that case
+ # we post the dialog as an after task instead.
set windowingsystem [tk windowingsystem]
if {$windowingsystem eq "aqua"} {
- set ok [mc Ok]
- } else {
- set ok [mc OK]
+ if $flag {
+ after 500 [list bgerror "$err" 0]
+ return
+ }
}
+ set ok [mc OK]
# Truncate the message if it is too wide (>maxLine characters) or
# too tall (>4 lines). Truncation occurs at the first point at
# which one of those conditions is met.
diff --git a/library/demos/puzzle.tcl b/library/demos/puzzle.tcl
index 4f7f955..eebe87a 100644
--- a/library/demos/puzzle.tcl
+++ b/library/demos/puzzle.tcl
@@ -73,7 +73,7 @@ for {set i 0} {$i < 15} {set i [expr {$i+1}]} {
set num [lindex $order $i]
set xpos($num) [expr {($i%4)*.25}]
set ypos($num) [expr {($i/4)*.25}]
- button $w.frame.$num -relief raised -text $num -highlightthickness 0 \
+ button $w.frame.$num -relief raised -text $num -bd 0 -highlightthickness 0 \
-command "puzzleSwitch $w $num"
place $w.frame.$num -relx $xpos($num) -rely $ypos($num) \
-relwidth .25 -relheight .25
diff --git a/library/menu.tcl b/library/menu.tcl
index ba66b92..8d06868 100644
--- a/library/menu.tcl
+++ b/library/menu.tcl
@@ -234,6 +234,7 @@ proc ::tk::MbLeave w {
}
}
+
# ::tk::MbPost --
# Given a menubutton, this procedure does all the work of posting
# its associated menu and unposting any other menu that is currently
@@ -282,101 +283,17 @@ proc ::tk::MbPost {w {x {}} {y {}}} {
set Priv(focus) [focus]
$menu activate none
GenerateMenuSelect $menu
-
- # If this looks like an option menubutton then post the menu so
- # that the current entry is on top of the mouse. Otherwise post
- # the menu just below the menubutton, as for a pull-down.
-
update idletasks
- if {[catch {
- switch [$w cget -direction] {
- above {
- set x [winfo rootx $w]
- set y [expr {[winfo rooty $w] - [winfo reqheight $menu]}]
- # if we go offscreen to the top, show as 'below'
- if {$y < [winfo vrooty $w]} {
- set y [expr {[winfo vrooty $w] + [winfo rooty $w] + [winfo reqheight $w]}]
- }
- PostOverPoint $menu $x $y
- }
- below {
- set x [winfo rootx $w]
- set y [expr {[winfo rooty $w] + [winfo height $w]}]
- # if we go offscreen to the bottom, show as 'above'
- set mh [winfo reqheight $menu]
- if {($y + $mh) > ([winfo vrooty $w] + [winfo vrootheight $w])} {
- set y [expr {[winfo vrooty $w] + [winfo vrootheight $w] + [winfo rooty $w] - $mh}]
- }
- PostOverPoint $menu $x $y
- }
- left {
- set x [expr {[winfo rootx $w] - [winfo reqwidth $menu]}]
- set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
- set entry [MenuFindName $menu [$w cget -text]]
- if {$entry eq ""} {
- set entry 0
- }
- if {[$w cget -indicatoron]} {
- if {$entry == [$menu index last]} {
- incr y [expr {-([$menu yposition $entry] \
- + [winfo reqheight $menu])/2}]
- } else {
- incr y [expr {-([$menu yposition $entry] \
- + [$menu yposition [expr {$entry+1}]])/2}]
- }
- }
- PostOverPoint $menu $x $y
- if {$entry ne "" \
- && [$menu entrycget $entry -state] ne "disabled"} {
- $menu activate $entry
- GenerateMenuSelect $menu
- }
- }
- right {
- set x [expr {[winfo rootx $w] + [winfo width $w]}]
- set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
- set entry [MenuFindName $menu [$w cget -text]]
- if {$entry eq ""} {
- set entry 0
- }
- if {[$w cget -indicatoron]} {
- if {$entry == [$menu index last]} {
- incr y [expr {-([$menu yposition $entry] \
- + [winfo reqheight $menu])/2}]
- } else {
- incr y [expr {-([$menu yposition $entry] \
- + [$menu yposition [expr {$entry+1}]])/2}]
- }
- }
- PostOverPoint $menu $x $y
- if {$entry ne "" \
- && [$menu entrycget $entry -state] ne "disabled"} {
- $menu activate $entry
- GenerateMenuSelect $menu
- }
- }
- default {
- if {[$w cget -indicatoron]} {
- if {$y eq ""} {
- set x [expr {[winfo rootx $w] + [winfo width $w]/2}]
- set y [expr {[winfo rooty $w] + [winfo height $w]/2}]
- }
- PostOverPoint $menu $x $y [MenuFindName $menu [$w cget -text]]
- } else {
- PostOverPoint $menu [winfo rootx $w] [expr {[winfo rooty $w]+[winfo height $w]}]
- }
- }
- }
- } msg opt]} {
+
+ if {[catch {PostMenubuttonMenu $w $menu} msg opt]} {
# Error posting menu (e.g. bogus -postcommand). Unpost it and
# reflect the error.
-
MenuUnpost {}
return -options $opt $msg
}
set Priv(tearoff) $tearoff
- if {$tearoff != 0} {
+ if {$tearoff != 0 && [tk windowingsystem] ne "aqua"} {
focus $menu
if {[winfo viewable $w]} {
SaveGrabInfo $w
@@ -576,11 +493,13 @@ proc ::tk::MenuMotion {menu x y state} {
if {[string is false $mode]} {
set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}]
if {[$menu type $index] eq "cascade"} {
+ # Catch these postcascade commands since the menu could be
+ # destroyed before they run.
set Priv(menuActivatedTimer) \
- [after $delay [list $menu postcascade active]]
+ [after $delay "catch {$menu postcascade active}"]
} else {
set Priv(menuDeactivatedTimer) \
- [after $delay [list $menu postcascade none]]
+ [after $delay "catch {$menu postcascade none}"]
}
}
}
@@ -1208,10 +1127,118 @@ proc ::tk::MenuFindName {menu s} {
return ""
}
+# ::tk::PostMenubuttonMenu --
+#
+# Given a menubutton and a menu, this procedure posts the menu at the
+# appropriate location. If the menubutton looks like an option
+# menubutton, meaning that the indicator is on and the direction is
+# neither above nor below, then the menu is posted so that the current
+# entry is vertically aligned with the menubutton. On the Mac this
+# will expose a small amount of the blue indicator on the right hand
+# side. On other platforms the entry is centered over the button.
+
+if {[tk windowingsystem] eq "aqua"} {
+ proc ::tk::PostMenubuttonMenu {button menu} {
+ set entry ""
+ if {[$button cget -indicatoron]} {
+ set entry [MenuFindName $menu [$button cget -text]]
+ if {$entry eq ""} {
+ set entry 0
+ }
+ }
+ set x [winfo rootx $button]
+ set y [expr {2 + [winfo rooty $button]}]
+ switch [$button cget -direction] {
+ above {
+ set entry ""
+ incr y [expr {4 - [winfo reqheight $menu]}]
+ }
+ below {
+ set entry ""
+ incr y [expr {2 + [winfo height $button]}]
+ }
+ left {
+ incr x [expr {-[winfo reqwidth $menu]}]
+ }
+ right {
+ incr x [winfo width $button]
+ }
+ default {
+ incr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}]
+ }
+ }
+ PostOverPoint $menu $x $y $entry
+ }
+} else {
+ proc ::tk::PostMenubuttonMenu {button menu} {
+ set entry ""
+ if {[$button cget -indicatoron]} {
+ set entry [MenuFindName $menu [$button cget -text]]
+ if {$entry eq ""} {
+ set entry 0
+ }
+ }
+ if {$entry ne ""} {
+ if {$entry == [$menu index last]} {
+ set entryHeight [expr {[winfo reqheight $menu] \
+ - [$menu yposition $entry]}]
+ } else {
+ set entryHeight [expr {[$menu yposition [expr {$entry+1}]] \
+ - [$menu yposition $entry]}]
+ }
+ }
+ set x [winfo rootx $button]
+ set y [winfo rooty $button]
+ switch [$button cget -direction] {
+ above {
+ incr y [expr {-[winfo reqheight $menu]}]
+ # if we go offscreen to the top, show as 'below'
+ if {$y < [winfo vrooty $button]} {
+ set y [expr {[winfo vrooty $button] + [winfo rooty $button]\
+ + [winfo reqheight $button]}]
+ }
+ set entry {}
+ }
+ below {
+ incr y [winfo height $button]
+ # if we go offscreen to the bottom, show as 'above'
+ set mh [winfo reqheight $menu]
+ if {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} {
+ set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \
+ + [winfo rooty $button] - $mh}]
+ }
+ set entry {}
+ }
+ left {
+ # It is not clear why this is needed.
+ if {[tk windowingsystem] eq "win32"} {
+ incr x [expr {-4 - [winfo reqwidth $button] / 2}]
+ }
+ incr x [expr {- [winfo reqwidth $menu]}]
+ }
+ right {
+ incr x [expr {[winfo width $button]}]
+ }
+ default {
+ if {[$button cget -indicatoron]} {
+ incr x [expr {([winfo width $button] - \
+ [winfo reqwidth $menu])/ 2}]
+ } else {
+ incr y [winfo height $button]
+ }
+ }
+ }
+ PostOverPoint $menu $x $y $entry
+ }
+}
+
# ::tk::PostOverPoint --
-# This procedure posts a given menu such that a given entry in the
-# menu is centered over a given point in the root window. It also
-# activates the given entry.
+#
+# This procedure posts a menu on the screen so that a given entry in
+# the menu is positioned with its upper left corner at a given point
+# in the root window. The procedure also activates that entry. If no
+# entry is specified the upper left corner of the entire menu is
+# placed at the point.
#
# Arguments:
# menu - Menu to post.
@@ -1220,19 +1247,24 @@ proc ::tk::MenuFindName {menu s} {
# If omitted or specified as {}, then the menu's
# upper-left corner goes at (x,y).
-proc ::tk::PostOverPoint {menu x y {entry {}}} {
- if {$entry ne ""} {
- if {$entry == [$menu index last]} {
- incr y [expr {-([$menu yposition $entry] \
- + [winfo reqheight $menu])/2}]
+if {[tk windowingsystem] ne "win32"} {
+ proc ::tk::PostOverPoint {menu x y {entry {}}} {
+ if {$entry ne ""} {
+ $menu post $x $y $entry
+ if {[$menu entrycget $entry -state] ne "disabled"} {
+ $menu activate $entry
+ GenerateMenuSelect $menu
+ }
} else {
- incr y [expr {-([$menu yposition $entry] \
- + [$menu yposition [expr {$entry+1}]])/2}]
+ $menu post $x $y
}
- incr x [expr {-[winfo reqwidth $menu]/2}]
+ return
}
-
- if {[tk windowingsystem] eq "win32"} {
+} else {
+ proc ::tk::PostOverPoint {menu x y {entry {}}} {
+ if {$entry ne ""} {
+ incr y [expr {-[$menu yposition $entry]}]
+ }
# osVersion is not available in safe interps
set ver 5
if {[info exists ::tcl_platform(osVersion)]} {
@@ -1248,7 +1280,7 @@ proc ::tk::PostOverPoint {menu x y {entry {}}} {
# manager provided with Vista and Windows 7.
if {$ver < 6} {
set yoffset [expr {[winfo screenheight $menu] \
- - $y - [winfo reqheight $menu] - 10}]
+ - $y - [winfo reqheight $menu] - 10}]
if {$yoffset < [winfo vrooty $menu]} {
# The bottom of the menu is offscreen, so adjust upwards
incr y [expr {$yoffset - [winfo vrooty $menu]}]
@@ -1260,11 +1292,11 @@ proc ::tk::PostOverPoint {menu x y {entry {}}} {
set y [winfo vrooty $menu]
}
}
- }
- $menu post $x $y
- if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
- $menu activate $entry
- GenerateMenuSelect $menu
+ $menu post $x $y
+ if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
+ $menu activate $entry
+ GenerateMenuSelect $menu
+ }
}
}
diff --git a/library/ttk/altTheme.tcl b/library/ttk/altTheme.tcl
index 6fc76f8..80ef415 100644
--- a/library/ttk/altTheme.tcl
+++ b/library/ttk/altTheme.tcl
@@ -96,10 +96,8 @@ namespace eval ttk::theme::alt {
ttk::style configure Treeview -background $colors(-window)
ttk::style map Treeview \
-background [list disabled $colors(-frame)\
- {!disabled !selected} $colors(-window) \
selected $colors(-selectbg)] \
-foreground [list disabled $colors(-disabledfg) \
- {!disabled !selected} black \
selected $colors(-selectfg)]
ttk::style configure TScale \
diff --git a/library/ttk/aquaTheme.tcl b/library/ttk/aquaTheme.tcl
index d6be5a3..a548d65 100644
--- a/library/ttk/aquaTheme.tcl
+++ b/library/ttk/aquaTheme.tcl
@@ -42,11 +42,9 @@ namespace eval ttk::theme::aqua {
ttk::style configure Treeview -rowheight 18 -background White
ttk::style map Treeview \
-background [list disabled systemDialogBackgroundInactive \
- {!disabled !selected} systemWindowBody \
{selected background} systemHighlightSecondary \
selected systemHighlight] \
-foreground [list disabled systemModelessDialogInactiveText \
- {!disabled !selected} black \
selected systemModelessDialogActiveText]
# Enable animation for ttk::progressbar widget:
diff --git a/library/ttk/clamTheme.tcl b/library/ttk/clamTheme.tcl
index 3c6f5c3..6935fc7 100644
--- a/library/ttk/clamTheme.tcl
+++ b/library/ttk/clamTheme.tcl
@@ -132,10 +132,8 @@ namespace eval ttk::theme::clam {
ttk::style configure Treeview -background $colors(-window)
ttk::style map Treeview \
-background [list disabled $colors(-frame)\
- {!disabled !selected} $colors(-window) \
selected $colors(-selectbg)] \
-foreground [list disabled $colors(-disabledfg) \
- {!disabled !selected} black \
selected $colors(-selectfg)]
ttk::style configure TLabelframe \
diff --git a/library/ttk/classicTheme.tcl b/library/ttk/classicTheme.tcl
index fefdb99..f237fba 100644
--- a/library/ttk/classicTheme.tcl
+++ b/library/ttk/classicTheme.tcl
@@ -99,10 +99,8 @@ namespace eval ttk::theme::classic {
ttk::style configure Treeview -background $colors(-window)
ttk::style map Treeview \
-background [list disabled $colors(-frame)\
- {!disabled !selected} $colors(-window) \
selected $colors(-selectbg)] \
-foreground [list disabled $colors(-disabledfg) \
- {!disabled !selected} black \
selected $colors(-selectfg)]
#
diff --git a/library/ttk/defaults.tcl b/library/ttk/defaults.tcl
index 4c1753d..a15d1d9 100644
--- a/library/ttk/defaults.tcl
+++ b/library/ttk/defaults.tcl
@@ -111,10 +111,8 @@ namespace eval ttk::theme::default {
-foreground $colors(-text) ;
ttk::style map Treeview \
-background [list disabled $colors(-frame)\
- {!disabled !selected} $colors(-window) \
selected $colors(-selectbg)] \
-foreground [list disabled $colors(-disabledfg) \
- {!disabled !selected} black \
selected $colors(-selectfg)]
# Combobox popdown frame
diff --git a/library/ttk/vistaTheme.tcl b/library/ttk/vistaTheme.tcl
index ecb39c9..094288c 100644
--- a/library/ttk/vistaTheme.tcl
+++ b/library/ttk/vistaTheme.tcl
@@ -48,10 +48,8 @@ namespace eval ttk::theme::vista {
ttk::style configure Treeview -background SystemWindow
ttk::style map Treeview \
-background [list disabled SystemButtonFace \
- {!disabled !selected} SystemWindow \
selected SystemHighlight] \
-foreground [list disabled SystemGrayText \
- {!disabled !selected} SystemWindowText \
selected SystemHighlightText]
# Label and Toolbutton
diff --git a/library/ttk/winTheme.tcl b/library/ttk/winTheme.tcl
index a7a2c79..db05b45 100644
--- a/library/ttk/winTheme.tcl
+++ b/library/ttk/winTheme.tcl
@@ -74,10 +74,8 @@ namespace eval ttk::theme::winnative {
ttk::style configure Treeview -background SystemWindow
ttk::style map Treeview \
-background [list disabled SystemButtonFace \
- {!disabled !selected} SystemWindow \
selected SystemHighlight] \
-foreground [list disabled SystemGrayText \
- {!disabled !selected} SystemWindowText \
selected SystemHighlightText]
ttk::style configure TProgressbar \
diff --git a/library/ttk/xpTheme.tcl b/library/ttk/xpTheme.tcl
index 5d8d09b..4c4f680 100644
--- a/library/ttk/xpTheme.tcl
+++ b/library/ttk/xpTheme.tcl
@@ -67,10 +67,8 @@ namespace eval ttk::theme::xpnative {
ttk::style configure Treeview -background SystemWindow
ttk::style map Treeview \
-background [list disabled SystemButtonFace \
- {!disabled !selected} SystemWindow \
selected SystemHighlight] \
-foreground [list disabled SystemGrayText \
- {!disabled !selected} SystemWindowText \
selected SystemHighlightText];
}
}
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index ea78d43..484dcf2 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -29,19 +29,10 @@
* be allowed when drawing the HITheme button.
*/
-#define HI_PADX 2
+#define HI_PADX 14
#define HI_PADY 1
/*
- * Some defines used to control what type of control is drawn.
- */
-
-#define DRAW_LABEL 0 /* Labels are treated genericly. */
-#define DRAW_CONTROL 1 /* Draw using the Native control. */
-#define DRAW_CUSTOM 2 /* Make our own button drawing. */
-#define DRAW_BEVEL 3
-
-/*
* The delay in milliseconds between pulsing default button redraws.
*/
#define PULSE_TIMER_MSECS 62 /* Largest value that didn't look stuttery */
@@ -52,7 +43,6 @@
typedef struct {
- int drawType;
Tk_3DBorder border;
int relief;
int offset; /* 0 means this is a normal widget. 1 means
@@ -271,11 +261,7 @@ TkpComputeButtonGeometry(
int txtWidth = 0, txtHeight = 0;
MacButton *mbPtr = (MacButton*)butPtr;
Tk_FontMetrics fm;
- DrawParams drawParams;
-
- /*
- * First figure out the size of the contents of the button.
- */
+ char *text = Tcl_GetString(butPtr->textPtr);
TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
@@ -283,7 +269,7 @@ TkpComputeButtonGeometry(
* If the indicator is on, get its size.
*/
- if ( butPtr->indicatorOn ) {
+ if (butPtr->indicatorOn) {
switch (butPtr->type) {
case TYPE_RADIO_BUTTON:
GetThemeMetric(kThemeMetricRadioButtonWidth, (SInt32 *)&butPtr->indicatorDiameter);
@@ -312,20 +298,19 @@ TkpComputeButtonGeometry(
if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
Tk_FreeTextLayout(butPtr->textLayout);
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
- Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
- butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
-
- txtWidth = butPtr->textWidth;
- txtHeight = butPtr->textHeight;
- charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
- Tk_GetFontMetrics(butPtr->tkfont, &fm);
- haveText = (txtWidth != 0 && txtHeight != 0);
+ text, -1, butPtr->wrapLength, butPtr->justify, 0,
+ &butPtr->textWidth, &butPtr->textHeight);
+
+ txtWidth = butPtr->textWidth + 2*butPtr->padX;
+ txtHeight = butPtr->textHeight + 2*butPtr->padY;
+ haveText = 1;
}
if (haveImage && haveText) { /* Image and Text */
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM:
+
/*
* Image is above or below text.
*/
@@ -335,14 +320,16 @@ TkpComputeButtonGeometry(
break;
case COMPOUND_LEFT:
case COMPOUND_RIGHT:
+
/*
* Image is left or right of text.
*/
- width += txtWidth + butPtr->padX;
+ width += txtWidth + 2*butPtr->padX;
height = (height > txtHeight ? height : txtHeight);
break;
case COMPOUND_CENTER:
+
/*
* Image and text are superimposed.
*/
@@ -354,26 +341,27 @@ TkpComputeButtonGeometry(
break;
}
width += butPtr->indicatorSpace;
-
} else if (haveImage) { /* Image only */
- width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
- height = butPtr->height > 0 ? butPtr->height : height;
-
+ width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
+ height = butPtr->height > 0 ? butPtr->height : height;
+ if (butPtr->type == TYPE_BUTTON) {
+ /* Allow room to shift the image. */
+ width += 2;
+ height += 2;
+ }
} else { /* Text only */
width = txtWidth + butPtr->indicatorSpace;
height = txtHeight;
if (butPtr->width > 0) {
- width = butPtr->width * charWidth;
+ charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
+ width = butPtr->width * charWidth + 2*butPtr->padX;
}
if (butPtr->height > 0) {
- height = butPtr->height * fm.linespace;
+ Tk_GetFontMetrics(butPtr->tkfont, &fm);
+ height = butPtr->height * fm.linespace + 2*butPtr->padY;
}
}
- /* Add padding */
- width += 2 * butPtr->padX;
- height += 2 * butPtr->padY;
-
/*
* Now figure out the size of the border decorations for the button.
*/
@@ -382,48 +370,35 @@ TkpComputeButtonGeometry(
butPtr->highlightWidth = 0;
}
- butPtr->inset = 0;
- butPtr->inset += butPtr->highlightWidth;
+ butPtr->inset = butPtr->borderWidth + butPtr->highlightWidth;
- if (TkMacOSXComputeButtonDrawParams(butPtr,&drawParams)) {
+ width += butPtr->inset*2;
+ height += butPtr->inset*2;
+ if ([NSApp macMinorVersion] == 6) {
+ width += 12;
+ }
+ if (mbPtr->btnkind == kThemePushButton) {
HIRect tmpRect;
HIRect contBounds;
- int paddingx = 0;
- int paddingy = 0;
+ /*
+ * A PushButton has a minimum size. We make sure that we
+ * are not underestimating the size by requesting the content
+ * size of a Pushbutton whose overall size is our content size
+ * expanded by the standard padding.
+ */
+
tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY);
-
HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
- /* If the content region has a minimum height, match it. */
if (height < contBounds.size.height) {
- height = contBounds.size.height;
+ height = contBounds.size.height;
}
-
- /* If the content region has a minimum width, match it. */
if (width < contBounds.size.width) {
- width = contBounds.size.width;
+ width = contBounds.size.width;
}
-
- /* Pad to fill difference between content bounds and button bounds. */
- paddingx = contBounds.origin.x;
- paddingy = contBounds.origin.y;
-
- if (height < paddingx - 4) {
- /* can't have buttons much shorter than button side diameter. */
- height = paddingx - 4;
- }
-
- } else {
- height += butPtr->borderWidth*2;
- width += butPtr->borderWidth*2;
- }
-
- width += butPtr->inset*2;
- height += butPtr->inset*2;
- if ([NSApp macMinorVersion] == 6) {
- width += 12;
+ height += 2*HI_PADY;
+ width += 2*HI_PADX;
}
-
Tk_GeometryRequest(butPtr->tkwin, width, height);
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}
@@ -570,7 +545,6 @@ DrawButtonImageAndText(
}
imageXOffset += x;
imageYOffset += y;
- textYOffset -= 1;
if (butPtr->image != NULL) {
if ((butPtr->selectImage != NULL) &&
@@ -594,6 +568,7 @@ DrawButtonImageAndText(
XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
}
+ y += 1; /* Tweak to match native buttons. */
Tk_DrawTextLayout(butPtr->display, pixmap,
dpPtr->gc, butPtr->textLayout,
x + textXOffset, y + textYOffset, 0, -1);
@@ -646,6 +621,7 @@ DrawButtonImageAndText(
butPtr->textWidth + butPtr->indicatorSpace,
butPtr->textHeight, &x, &y);
x += butPtr->indicatorSpace;
+ y += 1; /* Tweak to match native buttons */
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,
x, y, 0, -1);
}
@@ -1119,7 +1095,6 @@ TkMacOSXComputeButtonDrawParams(
}
}
-
dpPtr->border = butPtr->normalBorder;
if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
dpPtr->gc = butPtr->disabledGC;
@@ -1149,29 +1124,22 @@ TkMacOSXComputeButtonDrawParams(
}
}
- /*
- * Determine the draw type
- */
-
- if (butPtr->type == TYPE_LABEL) {
- dpPtr->drawType = DRAW_LABEL;
- } else if (butPtr->type == TYPE_BUTTON) {
- if (!dpPtr->hasImageOrBitmap) {
- dpPtr->drawType = DRAW_CONTROL;
- } else {
- dpPtr->drawType = DRAW_BEVEL;
- }
- } else if (butPtr->indicatorOn) {
- dpPtr->drawType = DRAW_CONTROL;
- } else if (dpPtr->hasImageOrBitmap) {
- dpPtr->drawType = DRAW_BEVEL;
- } else {
- dpPtr->drawType = DRAW_CUSTOM;
- }
-
- if ((dpPtr->drawType == DRAW_CONTROL) || (dpPtr->drawType == DRAW_BEVEL)) {
+ if (butPtr->type != TYPE_LABEL &&
+ (butPtr->type == TYPE_BUTTON ||
+ butPtr->indicatorOn ||
+ dpPtr->hasImageOrBitmap)) {
+
+ /*
+ * Draw this widget as a native control.
+ */
+
return 1;
} else {
+
+ /*
+ * Draw this widget from scratch.
+ */
+
return 0;
}
}
diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h
index a0b6a79..dd6be69 100644
--- a/macosx/tkMacOSXDefault.h
+++ b/macosx/tkMacOSXDefault.h
@@ -334,7 +334,7 @@
* Defaults for menubuttons:
*/
-#define DEF_MENUBUTTON_ANCHOR "center"
+#define DEF_MENUBUTTON_ANCHOR "w"
#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK
#define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG
@@ -342,7 +342,7 @@
#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
#define DEF_MENUBUTTON_BG_MONO WHITE
#define DEF_MENUBUTTON_BITMAP ""
-#define DEF_MENUBUTTON_BORDER_WIDTH "2"
+#define DEF_MENUBUTTON_BORDER_WIDTH "0"
#define DEF_MENUBUTTON_CURSOR ""
#define DEF_MENUBUTTON_DIRECTION "below"
#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
@@ -358,8 +358,8 @@
#define DEF_MENUBUTTON_INDICATOR "1"
#define DEF_MENUBUTTON_JUSTIFY "left"
#define DEF_MENUBUTTON_MENU ""
-#define DEF_MENUBUTTON_PADX "4"
-#define DEF_MENUBUTTON_PADY "3"
+#define DEF_MENUBUTTON_PADX "0"
+#define DEF_MENUBUTTON_PADY "0"
#define DEF_MENUBUTTON_RELIEF "flat"
#define DEF_MENUBUTTON_STATE "normal"
#define DEF_MENUBUTTON_TAKE_FOCUS "0"
diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c
index 589475c..932d4cb 100644
--- a/macosx/tkMacOSXEmbed.c
+++ b/macosx/tkMacOSXEmbed.c
@@ -272,7 +272,14 @@ TkpUseWindow(
}
usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);
- if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) {
+ if (usePtr == NULL) {
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "couldn't create child of window \"%s\"", string));
+ Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL);
+ }
+ return TCL_ERROR;
+ } else if (!(usePtr->flags & TK_CONTAINER)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"window \"%s\" doesn't have -container option set",
usePtr->pathName));
@@ -281,15 +288,9 @@ TkpUseWindow(
}
/*
- * The code below can probably be simplified given we have already
- * discovered 'usePtr' above.
- */
-
- /*
- * Save information about the container and the embedded window in a
- * Container structure. Currently, there must already be an existing
- * Container structure, since we only allow the case where both container
- * and embedded app. are in the same process.
+ * Since we do not allow embedding into windows belonging to a different
+ * process, we know that a container will exist showing the parent window
+ * as the parent. This loop finds that container.
*/
for (containerPtr = firstContainerPtr; containerPtr != NULL;
@@ -312,16 +313,6 @@ TkpUseWindow(
}
macWin->winPtr = winPtr;
- winPtr->privatePtr = macWin;
-
- /*
- * The grafPtr will be NULL for a Tk in Tk embedded window. It is none of
- * our business what it is for a Tk not in Tk embedded window, but we will
- * initialize it to NULL, and let the registerWinProc set it. In any case,
- * you must always use TkMacOSXGetDrawablePort to get the portPtr. It will
- * correctly find the container's port.
- */
-
macWin->view = nil;
macWin->context = NULL;
macWin->size = CGSizeZero;
@@ -333,6 +324,7 @@ TkpUseWindow(
macWin->toplevel = macWin;
macWin->toplevel->referenceCount++;
+ winPtr->privatePtr = macWin;
winPtr->flags |= TK_EMBEDDED;
/*
@@ -341,64 +333,28 @@ TkpUseWindow(
*/
macWin->flags |= TK_EMBEDDED;
+ macWin->xOff = parent->winPtr->privatePtr->xOff +
+ parent->winPtr->changes.border_width +
+ winPtr->changes.x;
+ macWin->yOff = parent->winPtr->privatePtr->yOff +
+ parent->winPtr->changes.border_width +
+ winPtr->changes.y;
/*
- * Now check whether it is embedded in another Tk widget. If not (the
- * first case below) we see if there is an in-process embedding handler
- * registered, and if so, let that fill in the rest of the macWin.
+ * Finish filling up the container structure with the embedded
+ * window's information.
*/
- if (containerPtr == NULL) {
- /*
- * If someone has registered an in-process embedding handler, then
- * see if it can handle this window...
- */
-
- if (tkMacOSXEmbedHandler == NULL ||
- tkMacOSXEmbedHandler->registerWinProc((long) parent,
- (Tk_Window) winPtr) != TCL_OK) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "The window ID %s does not correspond to a valid Tk Window",
- string));
- Tcl_SetErrorCode(interp, "TK", "EMBED", "HANDLE", NULL);
- return TCL_ERROR;
- }
-
- containerPtr = ckalloc(sizeof(Container));
+ containerPtr->embedded = (Window) macWin;
+ containerPtr->embeddedPtr = macWin->winPtr;
- containerPtr->parentPtr = NULL;
- containerPtr->embedded = (Window) macWin;
- containerPtr->embeddedPtr = macWin->winPtr;
- containerPtr->nextPtr = firstContainerPtr;
- firstContainerPtr = containerPtr;
- } else {
- /*
- * The window is embedded in another Tk window.
- */
-
- macWin->xOff = parent->winPtr->privatePtr->xOff +
- parent->winPtr->changes.border_width +
- winPtr->changes.x;
- macWin->yOff = parent->winPtr->privatePtr->yOff +
- parent->winPtr->changes.border_width +
- winPtr->changes.y;
-
- /*
- * Finish filling up the container structure with the embedded
- * window's information.
- */
-
- containerPtr->embedded = (Window) macWin;
- containerPtr->embeddedPtr = macWin->winPtr;
-
- /*
- * Create an event handler to clean up the Container structure when
- * tkwin is eventually deleted.
- */
+ /*
+ * Create an event handler to clean up the Container structure when
+ * tkwin is eventually deleted.
+ */
- Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
- winPtr);
- }
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
+ winPtr);
return TCL_OK;
}
@@ -542,9 +498,7 @@ TkMacOSXGetHostToplevel(
* TkpClaimFocus --
*
* This procedure is invoked when someone asks for the input focus to be
- * put on a window in an embedded application, but the application
- * doesn't currently have the focus. It requests the input focus from the
- * container application.
+ * put on a window in an embedded application.
*
* Results:
* None.
@@ -583,7 +537,7 @@ TkpClaimFocus(
event.xfocus.window = containerPtr->parent;
event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
event.xfocus.detail = force;
- Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
+ Tk_HandleEvent(&event);
}
/*
@@ -614,6 +568,7 @@ TkpTestembedCmd(
Container *containerPtr;
Tcl_DString dString;
char buffer[50];
+ Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
all = 1;
@@ -623,30 +578,40 @@ TkpTestembedCmd(
Tcl_DStringInit(&dString);
for (containerPtr = firstContainerPtr; containerPtr != NULL;
containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->embeddedPtr != NULL) {
+ embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
+ }
+ if (containerPtr->parentPtr != NULL) {
+ parentInterp = containerPtr->parentPtr->mainPtr->interp;
+ }
+ if (embeddedInterp != interp && parentInterp != interp) {
+ continue;
+ }
Tcl_DStringStartSublist(&dString);
+ /* Parent id */
if (containerPtr->parent == None) {
Tcl_DStringAppendElement(&dString, "");
} else if (all) {
- sprintf(buffer, "0x%x", (int) containerPtr->parent);
+ sprintf(buffer, "0x%lx", containerPtr->parent);
Tcl_DStringAppendElement(&dString, buffer);
} else {
Tcl_DStringAppendElement(&dString, "XXX");
}
- if (containerPtr->parentPtr == NULL) {
+ /* Parent pathName */
+ if (containerPtr->parentPtr == NULL ||
+ parentInterp != interp) {
Tcl_DStringAppendElement(&dString, "");
} else {
Tcl_DStringAppendElement(&dString,
containerPtr->parentPtr->pathName);
}
- if (containerPtr->embedded == None) {
- Tcl_DStringAppendElement(&dString, "");
- } else if (all) {
- sprintf(buffer, "0x%x", (int) containerPtr->embedded);
- Tcl_DStringAppendElement(&dString, buffer);
- } else {
- Tcl_DStringAppendElement(&dString, "XXX");
- }
- if (containerPtr->embeddedPtr == NULL) {
+ /*
+ * On X11 embedded is a wrapper, which does not exist on macOS.
+ */
+ Tcl_DStringAppendElement(&dString, "");
+ /* Embedded window pathName */
+ if (containerPtr->embeddedPtr == NULL ||
+ embeddedInterp != interp) {
Tcl_DStringAppendElement(&dString, "");
} else {
Tcl_DStringAppendElement(&dString,
@@ -904,6 +869,14 @@ EmbedStructureProc(
Tk_ErrorHandler errHandler;
if (eventPtr->type == ConfigureNotify) {
+
+ /*
+ * Send a ConfigureNotify to the embedded application.
+ */
+
+ if (containerPtr->embeddedPtr != None) {
+ TkDoConfigureNotify(containerPtr->embeddedPtr);
+ }
if (containerPtr->embedded != None) {
/*
* Ignore errors, since the embedded application could have
@@ -947,7 +920,6 @@ EmbedActivateProc(
XEvent *eventPtr) /* ResizeRequest event. */
{
Container *containerPtr = clientData;
-
if (containerPtr->embeddedPtr != NULL) {
if (eventPtr->type == ActivateNotify) {
TkGenerateActivateEvents(containerPtr->embeddedPtr,1);
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index d866b02..b9c9b6a 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -114,21 +114,16 @@ enum {
*
* This routine is a stub called by XSync, which is called during the Tk
* update command. The language specification does not require that the
- * update command be synchronous but many of the tests assume that is the
- * case. It is not naturally the case on macOS since many idle tasks are
- * run inside of the drawRect method of a window's contentView, and that
- * method will not be called until after this function returns. To make
- * the tests work, we attempt to force this to be synchronous by waiting
- * until drawRect has been called for each window. The mechanism we use
- * for this is to have drawRect post an ApplicationDefined NSEvent on the
- * AppKit event queue when it finishes drawing, and wait for it here.
+ * update command be synchronous but many of the tests implicitly assume
+ * that it is. It is definitely asynchronous on macOS since many idle
+ * tasks are run inside of the drawRect method of a window's contentView,
+ * which will not be called until after this function returns.
*
* Results:
* None.
*
- * Side effects:
- * Calls the drawRect method of the contentView of each visible
- * window.
+ * Side effects: Processes all pending idle events then calls the display
+ * method of each visible window.
*
*----------------------------------------------------------------------
*/
@@ -136,23 +131,12 @@ enum {
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
- NSArray *macWindows = [NSApp orderedWindows];
-
- if ([macWindows count] > 0) {
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
+ if (Tk_GetNumMainWindows() == 0) {
+ return;
}
- if ([NSApp isDrawing]) {
- for (NSWindow *w in macWindows) {
- if (TkMacOSXGetXWindow(w)) {
- [w setViewsNeedDisplay:YES];
- }
- }
- } else {
- for (NSWindow *w in macWindows) {
- if (TkMacOSXGetXWindow(w)) {
- [w display];
- }
- }
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
+ for (NSWindow *w in [NSApp orderedWindows]) {
+ [w display];
}
}
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 9d4d487..e1d56fa 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -122,7 +122,17 @@ static char scriptPath[PATH_MAX + 1] = "";
* method is called. Activating too early can cause the menu
* bar to be unresponsive.
*/
+
[NSApp activateIgnoringOtherApps: YES];
+
+ /*
+ * Process events to ensure that the root window is fully
+ * initialized. See ticket 56a1823c73.
+ */
+
+ [NSApp _lockAutoreleasePool];
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
+ [NSApp _unlockAutoreleasePool];
}
- (void) _setup: (Tcl_Interp *) interp
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index 3327f0a..543e7ab 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -24,9 +24,6 @@
*/
#define NS_KEYLOG 0
-
-static Tk_Window grabWinPtr = NULL;
- /* Current grab window, NULL if no grab. */
static Tk_Window keyboardGrabWinPtr = NULL;
/* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil;
@@ -500,11 +497,12 @@ XGrabKeyboard(
Time time)
{
keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window);
- if (keyboardGrabWinPtr && grabWinPtr) {
+ TkWindow *captureWinPtr = (TkWindow *)TkMacOSXGetCapture();
+ if (keyboardGrabWinPtr && captureWinPtr) {
NSWindow *w = TkMacOSXDrawableWindow(grab_window);
MacDrawable *macWin = (MacDrawable *) grab_window;
- if (w && macWin->toplevel->winPtr == (TkWindow*) grabWinPtr) {
+ if (w && macWin->toplevel->winPtr == (TkWindow*) captureWinPtr) {
if (modalSession) {
Tcl_Panic("XGrabKeyboard: already grabbed");
}
@@ -551,26 +549,6 @@ XUngrabKeyboard(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetCapture --
- *
- * Results:
- * Returns the current grab window
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-Tk_Window
-TkMacOSXGetCapture(void)
-{
- return grabWinPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkMacOSXGetModalSession --
*
* Results:
@@ -591,34 +569,6 @@ TkMacOSXGetModalSession(void)
/*
*----------------------------------------------------------------------
*
- * TkpSetCapture --
- *
- * This function captures the mouse so that all future events will be
- * reported to this window, even if the mouse is outside the window. If
- * the specified window is NULL, then the mouse is released.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the capture flag and captures the mouse.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkpSetCapture(
- TkWindow *winPtr) /* Capture window, or NULL. */
-{
- while (winPtr && !Tk_IsTopLevel(winPtr)) {
- winPtr = winPtr->parentPtr;
- }
- grabWinPtr = (Tk_Window) winPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* Tk_SetCaretPos --
*
* This enables correct placement of the XIM caret. This is called by
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index 8f3be9f..227c379 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -755,10 +755,13 @@ TkpDestroyMenuEntry(
*
* TkpPostMenu --
*
- * Posts a menu on the screen
+ * Posts a menu on the screen. If entry is < 0 then the menu is
+ * drawn so its top left corner is located at the point with
+ * screen coordinates (x, y). Otherwise the top left corner of
+ * the specified entry is located at that point.
*
* Results:
- * None.
+ * Returns a standard Tcl result.
*
* Side effects:
* The menu is posted and handled.
@@ -770,50 +773,52 @@ int
TkpPostMenu(
Tcl_Interp *interp, /* The interpreter this menu lives in */
TkMenu *menuPtr, /* The menu we are posting */
- int x, /* The global x-coordinate of the top, left-
- * hand corner of where the menu is supposed
- * to be posted. */
- int y) /* The global y-coordinate */
+ int x, int y, /* The screen coordinates where the top left
+ * corner of the menu, or of the specified
+ * entry, will be located. */
+ int index)
{
+ int result;
+ Tk_Window root = Tk_MainWindow(interp);
-
- /* Get the object that holds this Tk Window.*/
- Tk_Window root;
- root = Tk_MainWindow(interp);
if (root == NULL) {
return TCL_ERROR;
}
-
Drawable d = Tk_WindowId(root);
NSView *rootview = TkMacOSXGetRootControl(d);
NSWindow *win = [rootview window];
- int result;
+ NSView *view = [win contentView];
+ NSMenu *menu = (NSMenu *) menuPtr->platformData;
+ NSInteger itemIndex = index;
+ NSInteger numItems = [menu numberOfItems];
+ NSMenuItem *item = nil;
+ NSPoint location = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
inPostMenu = 1;
-
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
inPostMenu = 0;
return result;
}
+ if (itemIndex >= numItems) {
+ itemIndex = numItems - 1;
+ }
+ if (itemIndex >= 0) {
+ item = [menu itemAtIndex:itemIndex];
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
- int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
- NSView *view = [win contentView];
- NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
-
- frame.origin = [view convertPoint:
- [win tkConvertPointFromScreen:frame.origin] fromView:nil];
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
- NSMenu *menu = (NSMenu *) menuPtr->platformData;
- NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
- initTextCell:@"" pullsDown:NO];
-
- [popUpButtonCell setAltersStateOfSelectedItem:NO];
- [popUpButtonCell setMenu:menu];
- [popUpButtonCell selectItem:nil];
- [popUpButtonCell performClickWithFrame:frame inView:view];
- [popUpButtonCell release];
- Tcl_SetServiceMode(oldMode);
+ [menu popUpMenuPositioningItem:item
+ atLocation:[win tkConvertPointFromScreen:location]
+ inView:view];
inPostMenu = 0;
return TCL_OK;
}
@@ -821,6 +826,109 @@ TkpPostMenu(
/*
*----------------------------------------------------------------------
*
+ * TkpPostTearoffMenu --
+ *
+ * Tearoff menus are not supported on the Mac. This placeholder
+ * function, which is simply a copy of the unix function, posts a
+ * completely useless window with a black background on the screen. If
+ * entry is < 0 then the window is positioned so that its top left corner
+ * is located at the point with screen coordinates (x, y). Otherwise the
+ * window position is offset so that top left corner of the specified
+ * entry would be located at that point, if there actually were a menu.
+ *
+ * Mac menus steal all mouse or keyboard input from the application until
+ * the menu is dismissed, with or without a selection, by a mouse or key
+ * event. Posting a Mac menu in a regression test will cause the test to
+ * halt waiting for user input. This is why the TkpPostMenu function is
+ * not being used as the placeholder.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A useless window is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter this menu lives in */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y, int index) /* The screen coordinates where the top left
+ * corner of the menu, or of the specified
+ * entry, will be located. */
+{
+ int vRootX, vRootY, vRootWidth, vRootHeight;
+ int result;
+
+ if (index >= menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
+ TkActivateMenuEntry(menuPtr, -1);
+ TkRecomputeMenu(menuPtr);
+ result = TkPostCommand(menuPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Adjust the position of the menu if necessary to keep it visible on the
+ * screen. There are two special tricks to make this work right:
+ *
+ * 1. If a virtual root window manager is being used then the coordinates
+ * are in the virtual root window of menuPtr's parent; since the menu
+ * uses override-redirect mode it will be in the *real* root window for
+ * the screen, so we have to map the coordinates from the virtual root
+ * (if any) to the real root. Can't get the virtual root from the menu
+ * itself (it will never be seen by the wm) so use its parent instead
+ * (it would be better to have an an option that names a window to use
+ * for this...).
+ * 2. The menu may not have been mapped yet, so its current size might be
+ * the default 1x1. To compute how much space it needs, use its
+ * requested size, not its actual size.
+ */
+
+ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
+ &vRootWidth, &vRootHeight);
+ vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
+ if (x > vRootX + vRootWidth) {
+ x = vRootX + vRootWidth;
+ }
+ if (x < vRootX) {
+ x = vRootX;
+ }
+ vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
+ if (y > vRootY + vRootHeight) {
+ y = vRootY + vRootHeight;
+ }
+ if (y < vRootY) {
+ y = vRootY;
+ }
+ Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
+ if (!Tk_IsMapped(menuPtr->tkwin)) {
+ Tk_MapWindow(menuPtr->tkwin);
+ }
+ TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpSetWindowMenuBar --
*
* Associates a given menu with a window.
@@ -877,26 +985,47 @@ TkpSetMainMenubar(
{
static Tcl_Interp *currentInterp = NULL;
TKMenu *menu = nil;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+
+ /*
+ * We will be called when an embedded window receives an ActivationNotify
+ * event, but we should not change the menubar in that case.
+ */
+
+ if (Tk_IsEmbedded(winPtr)) {
+ return;
+ }
if (menuName) {
- TkWindow *winPtr = (TkWindow *) tkwin;
+ Tk_Window menubar = NULL;
+ if (winPtr->wmInfoPtr &&
+ winPtr->wmInfoPtr->menuPtr &&
+ winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
+ menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
+ }
+
+ /*
+ * Attempt to find the NSMenu directly. If that fails, ask Tk to find it.
+ */
- if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
- winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
- winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
- !strcmp(menuName, Tk_PathName(
- winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {
+ if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {
menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
} else {
TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
menuName);
-
if (menuRefPtr && menuRefPtr->menuPtr &&
menuRefPtr->menuPtr->platformData) {
menu = (TKMenu *) menuRefPtr->menuPtr->platformData;
}
}
}
+
+ /*
+ * If we couldn't find a menu, do nothing unless the window belongs
+ * to a different application. In that case, install the default
+ * menubar.
+ */
+
if (menu || interp != currentInterp) {
[NSApp tkSetMainMenu:menu];
}
@@ -909,8 +1038,8 @@ TkpSetMainMenubar(
* CheckForSpecialMenu --
*
* Given a menu, check to see whether or not it is a cascade in a menubar
- * with one of the special names .apple, .help or .window If it is, the
- * entry that points to this menu will be marked.
+ * with one of the special names ".apple", ".help" or ".window". If it
+ * is, the entry that points to this menu will be marked.
*
* Results:
* None.
@@ -1087,26 +1216,31 @@ void
TkpComputeStandardMenuGeometry(
TkMenu *menuPtr) /* Structure describing menu. */
{
+ NSSize menuSize;
Tk_Font tkfont, menuFont;
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
int modifierCharWidth, menuModifierCharWidth;
int x, y, modifierWidth, labelWidth, indicatorSpace;
int windowWidth, windowHeight, accelWidth;
- int i, j, lastColumnBreak, maxWidth;
+ int i, maxWidth;
int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
- TkMenuEntry *mePtr, *columnEntryPtr;
+ TkMenuEntry *mePtr;
int haveAccel = 0;
- if (menuPtr->tkwin == NULL) {
+ /*
+ * Do nothing if this menu is a clone.
+ */
+ if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
return;
}
-
+
+ menuSize = [(NSMenu *)menuPtr->platformData size];
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
&borderWidth);
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
&activeBorderWidth);
x = y = borderWidth;
- windowHeight = maxWidth = lastColumnBreak = 0;
+ windowHeight = maxWidth = 0;
maxIndicatorSpace = 0;
/*
@@ -1133,6 +1267,9 @@ TkpComputeStandardMenuGeometry(
for (i = 0; i < menuPtr->numEntries; i++) {
mePtr = menuPtr->entries[i];
+ if (mePtr->type == TEAROFF_ENTRY) {
+ continue;
+ }
if (mePtr->fontPtr == NULL) {
tkfont = menuFont;
fmPtr = &menuMetrics;
@@ -1143,26 +1280,8 @@ TkpComputeStandardMenuGeometry(
fmPtr = &entryMetrics;
modifierCharWidth = ModifierCharWidth(tkfont);
}
-
- if ((i > 0) && mePtr->columnBreak) {
- if (maxIndicatorSpace != 0) {
- maxIndicatorSpace += 2;
- }
- for (j = lastColumnBreak; j < i; j++) {
- columnEntryPtr = menuPtr->entries[j];
- columnEntryPtr->indicatorSpace = maxIndicatorSpace;
- columnEntryPtr->width = maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth;
- columnEntryPtr->x = x;
- columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
- }
- x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth;
- maxWidth = maxIndicatorSpace = 0;
- lastColumnBreak = i;
- y = borderWidth;
- }
accelWidth = modifierWidth = indicatorSpace = 0;
- if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
+ if (mePtr->type == SEPARATOR_ENTRY) {
mePtr->height = menuSeparatorHeight;
} else {
/*
@@ -1176,16 +1295,16 @@ TkpComputeStandardMenuGeometry(
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
int haveImage = 0, width = 0, height = 0;
-
if (mePtr->image) {
Tk_SizeOfImage(mePtr->image, &width, &height);
haveImage = 1;
+ height += 2; /* tweak */
} else if (mePtr->bitmapPtr) {
Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
mePtr->bitmapPtr);
-
Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
haveImage = 1;
+ height += 2; /* tweak */
}
if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
NSAttributedString *attrTitle = [menuItem attributedTitle];
@@ -1197,11 +1316,8 @@ TkpComputeStandardMenuGeometry(
size = [[menuItem title] sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)];
}
- size.width += menuTextLeadingEdgeMargin +
- menuTextTrailingEdgeMargin;
- if (size.height < fmPtr->linespace) {
- size.height = fmPtr->linespace;
- }
+ size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
+ size.height -= 1; /* tweak */
if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
int margin = width + menuIconTrailingEdgeMargin;
@@ -1217,9 +1333,11 @@ TkpComputeStandardMenuGeometry(
height = size.height;
}
}
+ else {
+ /* image only. */
+ }
labelWidth = width + menuItemExtraWidth;
mePtr->height = height + menuItemExtraHeight;
-
if (mePtr->type == CASCADE_ENTRY) {
modifierWidth = modifierCharWidth;
} else if (mePtr->accelLength == 0) {
@@ -1250,30 +1368,18 @@ TkpComputeStandardMenuGeometry(
if (entryWidth > maxWidth) {
maxWidth = entryWidth;
}
+ menuPtr->entries[i]->width = entryWidth;
mePtr->height += 2 * activeBorderWidth;
}
+ mePtr->x = x;
mePtr->y = y;
y += menuPtr->entries[i]->height + borderWidth;
- if (y > windowHeight) {
- windowHeight = y;
- }
}
-
- for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
- columnEntryPtr = menuPtr->entries[j];
- columnEntryPtr->indicatorSpace = maxIndicatorSpace;
- columnEntryPtr->width = maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth;
- columnEntryPtr->x = x;
- columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
- }
- windowWidth = x + maxIndicatorSpace + maxWidth
- + 2 * activeBorderWidth + borderWidth;
- windowHeight += borderWidth;
-
+ windowWidth = menuSize.width;
if (windowWidth <= 0) {
windowWidth = 1;
}
+ windowHeight = menuSize.height;
if (windowHeight <= 0) {
windowHeight = 1;
}
diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c
index 1acefe5..b2b4b76 100644
--- a/macosx/tkMacOSXMenubutton.c
+++ b/macosx/tkMacOSXMenubutton.c
@@ -47,17 +47,23 @@ typedef struct MacMenuButton {
} MacMenuButton;
/*
- * Forward declarations for procedures defined later in this file:
+ * Forward declarations for static functions defined later in this file:
*/
static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr);
-static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
-static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo * info, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
+static void MenuButtonBackgroundDrawCB (MacMenuButton *ptr, SInt16 depth,
+ Boolean isColorDev);
+static void MenuButtonContentDrawCB (ThemeButtonKind kind,
+ const HIThemeButtonDrawInfo * info,
+ MacMenuButton *ptr, SInt16 depth,
+ Boolean isColorDev);
static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr);
-static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo* drawinfo);
-static int TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, DrawParams * dpPtr);
-static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr,
- GC gc, Pixmap pixmap);
+static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr,
+ ThemeButtonKind* btnkind,
+ HIThemeButtonDrawInfo* drawinfo);
+static void TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr,
+ DrawParams * dpPtr);
+static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr, GC gc, Pixmap pixmap);
static void DrawMenuButtonImageAndText(TkMenuButton* butPtr);
/*
@@ -70,11 +76,45 @@ Tk_ClassProcs tkpMenubuttonClass = {
TkMenuButtonWorldChanged, /* worldChangedProc */
};
+/*
+ * We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
+ * However, we do not use the NSPopUpButton class for this control. Instead we
+ * render the Pop-Up Button using the HITheme library. This imposes some
+ * constraints on what can be done. The HITheme renderer allows only specific
+ * dimensions for the button.
+ *
+ * The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds
+ * rectangle. However the button is always drawn as a rounded box which is 22
+ * pixels high. If the bounds rectangle is less than 22 pixels high, the
+ * button is drawn at the top of the rectangle and the bottom of the button is
+ * clipped away. So we set a minimum height of 22 pixels for a Menubutton. If
+ * the bounds rectangle is more than 22 pixels high, then the button is drawn
+ * centered vertically in the bounds rectangle.
+ *
+ * The content rectangle of the button is inset by 14 pixels on the left and 28
+ * pixels on the right. The rightmost part of the button contains the blue
+ * double-arrow symbol which is 28 pixels wide.
+ *
+ * To maintain compatibility with code that runs on multiple operating systems,
+ * the width and height of the content rectangle includes the borderWidth, the
+ * highlightWidth and the padX and padY dimensions of the Menubutton. However,
+ * to be consistent with the standard Apple appearance, the content is always
+ * be drawn at the left side of the content rectangle. All of the excess space
+ * appears on the right side of the content, and the anchor property is
+ * ignored. The easiest way to comply with Apple's Human Interface Guidelines
+ * would be to set bd = highlightthickness = padx = 0 and to specify an
+ * explicit width for the button. Apple also recommends using the same width
+ * for all Pop-Up Buttons in a given window.
+ */
+
+#define LEFT_INSET 8
+#define RIGHT_INSET 28
+#define MIN_HEIGHT 22
/*
*----------------------------------------------------------------------
*
- * TkpCreateMenuButton --
+ * TkpCreateMenuButton --
*
* Allocate a new TkMenuButton structure.
*
@@ -93,13 +133,12 @@ TkpCreateMenuButton(
{
MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
- Tk_CreateEventHandler(tkwin, ActivateMask,
- MenuButtonEventProc, (ClientData) mbPtr);
+ Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc,
+ (ClientData) mbPtr);
mbPtr->flags = FIRST_DRAW;
mbPtr->btnkind = kThemePopupButton;
bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
-
return (TkMenuButton *) mbPtr;
}
@@ -165,12 +204,13 @@ TkpDisplayMenuButton(
* TkpDestroyMenuButton --
*
* Free data structures associated with the menubutton control.
+ * This is a no-op on the Mac.
*
* Results:
* None.
*
* Side effects:
- * Restores the default control state.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -204,15 +244,12 @@ TkpComputeMenuButtonGeometry(butPtr)
register TkMenuButton *butPtr; /* Widget record for menu button. */
{
int width, height, avgWidth, haveImage = 0, haveText = 0;
- MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
int txtWidth, txtHeight;
Tk_FontMetrics fm;
- DrawParams drawParams;
- int paddingx = 0;
- int paddingy = 0;
+ int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;
/*
- * First figure out the size of the contents of the button.
+ * First compute the size of the contents of the button.
*/
width = 0;
@@ -221,8 +258,6 @@ TkpComputeMenuButtonGeometry(butPtr)
txtHeight = 0;
avgWidth = 0;
- TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
-
if (butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
@@ -231,17 +266,16 @@ TkpComputeMenuButtonGeometry(butPtr)
haveImage = 1;
}
- if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
+ if (butPtr->text && strlen(butPtr->text) > 0) {
+ haveText = 1;
Tk_FreeTextLayout(butPtr->textLayout);
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
butPtr->text, -1, butPtr->wrapLength,
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
-
txtWidth = butPtr->textWidth;
txtHeight = butPtr->textHeight;
avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
Tk_GetFontMetrics(butPtr->tkfont, &fm);
- haveText = (txtWidth != 0 && txtHeight != 0);
}
/*
@@ -251,7 +285,7 @@ TkpComputeMenuButtonGeometry(butPtr)
* image, because otherwise it is not really a compound button.
*/
- if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
+ if (haveImage && haveText) {
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM: {
@@ -293,76 +327,29 @@ TkpComputeMenuButtonGeometry(butPtr)
}
} else {
- if (haveImage) {
+ if (haveImage) { /* Image only */
if (butPtr->width > 0) {
width = butPtr->width;
}
if (butPtr->height > 0) {
height = butPtr->height;
}
- } else {
+ } else { /* Text only */
width = txtWidth;
height = txtHeight;
if (butPtr->width > 0) {
- width = butPtr->width * avgWidth;
+ width = butPtr->width * avgWidth + 2*butPtr->padX;
}
if (butPtr->height > 0) {
- height = butPtr->height * fm.linespace;
+ height = butPtr->height * fm.linespace + 2*butPtr->padY;
}
}
}
- width += 2 * butPtr->padX - 2;
- height += 2 * butPtr->padY - 2;
-
- /*Add padding for button arrows.*/
- width += 22;
-
- /*
- * Now figure out the size of the border decorations for the button.
- */
-
- if (butPtr->highlightWidth < 0) {
- butPtr->highlightWidth = 0;
- }
- butPtr->inset = 0;
- butPtr->inset += butPtr->highlightWidth;
-
- TkMacOSXComputeMenuButtonDrawParams(butPtr,&drawParams);
-
- HIRect tmpRect;
- HIRect contBounds;
-
- tmpRect = CGRectMake(0, 0, width, height);
-
- HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
-
-
-
- /* If the content region has a minimum height, match it. */
- if (height < contBounds.size.height) {
- height = contBounds.size.height;
- }
-
- /* If the content region has a minimum width, match it. */
- if (width < contBounds.size.width) {
- width = contBounds.size.width;
- }
-
- /* Pad to fill difference between content bounds and button bounds. */
- paddingx = tmpRect.origin.x - contBounds.origin.x;
- paddingy = tmpRect.origin.y - contBounds.origin.y;
-
- if (paddingx > 0) {
- width += paddingx;
- }
- if (paddingy > 0) {
- height += paddingy;
- }
-
- width += butPtr->inset*2;
- height += butPtr->inset*2;
-
-
+
+ butPtr->inset = highlightWidth + butPtr->borderWidth;
+ width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;
+ height += 2*butPtr->inset;
+ height = height < MIN_HEIGHT ? MIN_HEIGHT : height;
Tk_GeometryRequest(butPtr->tkwin, width, height);
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}
@@ -427,8 +414,8 @@ DrawMenuButtonImageAndText(
pressed = 1;
}
- haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
- if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
+ haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
+ if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
int x = 0;
int y = 0;
textXOffset = 0;
@@ -446,8 +433,8 @@ DrawMenuButtonImageAndText(
imageYOffset = butPtr->textHeight + butPtr->padY;
}
fullHeight = height + butPtr->textHeight + butPtr->padY;
- fullWidth = (width > butPtr->textWidth ? width :
- butPtr->textWidth);
+ fullWidth = (width > butPtr->textWidth ?
+ width : butPtr->textWidth);
textXOffset = (fullWidth - butPtr->textWidth)/2;
imageXOffset = (fullWidth - width)/2;
break;
@@ -489,10 +476,10 @@ DrawMenuButtonImageAndText(
}
TkComputeAnchor(butPtr->anchor, tkwin,
- butPtr->padX + butPtr->borderWidth,
- butPtr->padY + butPtr->borderWidth,
+ butPtr->padX + butPtr->inset,
+ butPtr->padY + butPtr->inset,
fullWidth, fullHeight, &x, &y);
- imageXOffset += x;
+ imageXOffset = LEFT_INSET;
imageYOffset += y;
textYOffset -= 1;
@@ -517,36 +504,32 @@ DrawMenuButtonImageAndText(
butPtr->underline);
} else {
if (haveImage) {
- int x = 0;
- int y;
+ int x, y;
TkComputeAnchor(butPtr->anchor, tkwin,
butPtr->padX + butPtr->borderWidth,
butPtr->padY + butPtr->borderWidth,
width, height, &x, &y);
- imageXOffset += x;
- imageYOffset += y;
-
- if (butPtr->image != NULL) {
- Tk_RedrawImage(butPtr->image, 0, 0, width, height,
- pixmap, imageXOffset, imageYOffset);
+ imageXOffset = LEFT_INSET;
+ imageYOffset += y;
+ if (butPtr->image != NULL) {
+ Tk_RedrawImage(butPtr->image, 0, 0, width, height,
+ pixmap, imageXOffset, imageYOffset);
} else {
XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
XCopyPlane(butPtr->display, butPtr->bitmap,
- pixmap, dpPtr->gc,
- 0, 0, (unsigned int) width,
- (unsigned int) height,
- imageXOffset, imageYOffset, 1);
+ pixmap, dpPtr->gc,
+ 0, 0, (unsigned int) width,
+ (unsigned int) height,
+ imageXOffset, imageYOffset, 1);
XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
}
} else {
- /*Move x back by eight pixels to give the menubutton arrows room.*/
- int x = 0;
- int y;
- textXOffset = 8;
+ int x, y;
+ textXOffset = LEFT_INSET;
TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
butPtr->textWidth, butPtr->textHeight, &x, &y);
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
- butPtr->textLayout, x - textXOffset, y, 0, -1);
+ butPtr->textLayout, textXOffset, y, 0, -1);
y += butPtr->textHeight/2;
}
}
@@ -578,7 +561,6 @@ TkMacOSXDrawMenuButton(
* the bevel button */
Pixmap pixmap) /* The pixmap we are drawing into - needed
* for the bevel button */
-
{
TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
TkWindow * winPtr;
@@ -591,10 +573,9 @@ TkMacOSXDrawMenuButton(
TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
- cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, Tk_Width(butPtr->tkwin),Tk_Height(butPtr->tkwin));
-
- cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
-
+ cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
+ Tk_Width(butPtr->tkwin),
+ Tk_Height(butPtr->tkwin));
if (useNewerHITools == 1) {
HIRect contHIRec;
@@ -617,17 +598,15 @@ TkMacOSXDrawMenuButton(
hiinfo.animation.time.start = hiinfo.animation.time.current;
}
- HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);
-
+ HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
+ kHIThemeOrientationNormal, &contHIRec);
TkMacOSXRestoreDrawingContext(&dc);
-
- MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true);
+ MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo,
+ (MacMenuButton *)mbPtr, 32, true);
} else {
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
return;
}
-
-
TkMacOSXRestoreDrawingContext(&dc);
}
mbPtr->lastdrawinfo = mbPtr->drawinfo;
@@ -696,8 +675,7 @@ MenuButtonContentDrawCB (
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
}
-
- DrawMenuButtonImageAndText( butPtr);
+ DrawMenuButtonImageAndText(butPtr);
}
/*
@@ -761,19 +739,18 @@ MenuButtonEventProc(
*/
static void
-TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo)
+TkMacOSXComputeMenuButtonParams(
+ TkMenuButton * butPtr,
+ ThemeButtonKind* btnkind,
+ HIThemeButtonDrawInfo *drawinfo)
{
MacMenuButton *mbPtr = (MacMenuButton *)butPtr;
- if (butPtr->image || butPtr->bitmap) {
+ if (butPtr->image || butPtr->bitmap || butPtr->text) {
/* TODO: allow for Small and Mini menubuttons. */
*btnkind = kThemePopupButton;
- } else {
- if (!butPtr->text || !*butPtr->text) {
- *btnkind = kThemeArrowButton;
- } else {
- *btnkind = kThemePopupButton;
- }
+ } else { /* This should never happen. */
+ *btnkind = kThemeArrowButton;
}
drawinfo->value = kThemeButtonOff;
@@ -812,24 +789,25 @@ TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind,
*
* TkMacOSXComputeMenuButtonDrawParams --
*
- * This procedure computes the various parameters used
- * when drawing a button
- * These are determined by the various tk button parameters
+ * This procedure selects an appropriate drawing context for
+ * drawing a menubutton.
*
* Results:
- * 1 if control will be used, 0 otherwise.
+ * None.
*
* Side effects:
- * Sets the button draw parameters
+ * Sets the button draw parameters.
*
*----------------------------------------------------------------------
*/
-static int
-TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
+static void
+TkMacOSXComputeMenuButtonDrawParams(
+ TkMenuButton * butPtr,
+ DrawParams * dpPtr)
{
- dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
- || (butPtr->bitmap != None));
+ dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) ||
+ (butPtr->bitmap != None));
dpPtr->border = butPtr->normalBorder;
if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
dpPtr->gc = butPtr->disabledGC;
@@ -839,8 +817,6 @@ TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
} else {
dpPtr->gc = butPtr->normalTextGC;
}
-
- return 1;
}
/*
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 7b83679..ec713d4 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -24,6 +24,7 @@ typedef struct {
Point global;
Point local;
} MouseEventData;
+static Tk_Window captureWinPtr = NULL; /* Current capture window; may be NULL. */
static int GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int ButtonModifiers2State(UInt32 buttonState,
@@ -47,15 +48,17 @@ enum {
@implementation TKApplication(TKMouseEvent)
- (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
{
-#ifdef TK_MAC_DEBUG_EVENTS
- TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
-#endif
NSWindow* eventWindow = [theEvent window];
NSEventType eventType = [theEvent type];
+ TkWindow *winPtr, *grabWinPtr;
+ Tk_Window tkwin;
#if 0
NSTrackingArea *trackingArea = nil;
NSInteger eventNumber, clickCount, buttonNumber;
#endif
+#ifdef TK_MAC_DEBUG_EVENTS
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
+#endif
switch (eventType) {
case NSMouseEntered:
case NSMouseExited:
@@ -87,51 +90,94 @@ enum {
[_windowWithMouse retain];
}
- /* Create an Xevent to add to the Tk queue. */
+ /*
+ * Compute the mouse position in Tk screen coordinates (global) and in
+ * the Tk coordinates of its containing Tk Window.
+ */
+
NSPoint global, local = [theEvent locationInWindow];
- if (eventWindow) { /* local will be in window coordinates. */
+
+ /*
+ * If the event has no NSWindow, try using the cached NSWindow from the
+ * last mouse event.
+ */
+
+ if (eventWindow == NULL) {
+ eventWindow = _windowWithMouse;
+ }
+ if (eventWindow) {
+
+ /*
+ * Set the local mouse position to its NSWindow flipped coordinates,
+ * with the origin at top left, and the global mouse position to the
+ * flipped screen coordinates.
+ */
+
global = [eventWindow tkConvertPointToScreen: local];
local.y = [eventWindow frame].size.height - local.y;
global.y = tkMacOSXZeroScreenHeight - global.y;
- } else { /* local will be in screen coordinates. */
- if (_windowWithMouse ) {
- eventWindow = _windowWithMouse;
- global = local;
- local = [eventWindow tkConvertPointFromScreen: local];
- local.y = [eventWindow frame].size.height - local.y;
- global.y = tkMacOSXZeroScreenHeight - global.y;
- } else { /* We have no window. Use the screen???*/
- local.y = tkMacOSXZeroScreenHeight - local.y;
- global = local;
- }
+
+ } else {
+
+ /*
+ * As a last resort, with no NSWindow to work with, set both local and
+ * global to the screen coordinates.
+ */
+
+ local.y = tkMacOSXZeroScreenHeight - local.y;
+ global = local;
}
- TkWindow *winPtr = TkMacOSXGetTkWindow(eventWindow);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ /*
+ * Find the toplevel which corresponds to the event NSWindow.
+ */
- if (tkwin) {
- TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
- if (grabWinPtr &&
- grabWinPtr != winPtr &&
- !winPtr->dispPtr->grabFlags && /* this means the grab is local. */
- grabWinPtr->mainPtr == winPtr->mainPtr) {
- return theEvent;
- }
- } else {
+ winPtr = TkMacOSXGetTkWindow(eventWindow);
+ if (winPtr == NULL) {
tkwin = TkMacOSXGetCapture();
+ winPtr = (TkWindow *)tkwin;
+ } else {
+ tkwin = (Tk_Window) winPtr;
}
if (!tkwin) {
TkMacOSXDbgMsg("tkwin == NULL");
return theEvent; /* Give up. No window for this event. */
- } else {
- winPtr = (TkWindow *)tkwin;
}
+ /*
+ * If another toplevel has a grab, we ignore the event.
+ */
+
+ grabWinPtr = winPtr->dispPtr->grabWinPtr;
+ if (grabWinPtr &&
+ grabWinPtr != winPtr &&
+ !winPtr->dispPtr->grabFlags && /* this means the grab is local. */
+ grabWinPtr->mainPtr == winPtr->mainPtr) {
+ return theEvent;
+ }
+
+ /*
+ * Convert local from NSWindow flipped coordinates to the toplevel's
+ * coordinates.
+ */
+
local.x -= winPtr->wmInfoPtr->xInParent;
local.y -= winPtr->wmInfoPtr->yInParent;
+ /*
+ * Find the containing Tk window, and convert local into the coordinates
+ * of the Tk window. (The converted local coordinates are only needed
+ * for scrollwheel events.)
+ */
+
int win_x, win_y;
tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
+ local.x = win_x;
+ local.y = win_y;
+
+ /*
+ * Generate an XEvent for this mouse event.
+ */
unsigned int state = 0;
NSInteger button = [theEvent buttonNumber];
@@ -181,11 +227,21 @@ enum {
}
if (eventType != NSScrollWheel) {
+
+ /*
+ * For normal mouse events, Tk_UpdatePointer will send the XEvent.
+ */
+
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
#endif
Tk_UpdatePointer(tkwin, global.x, global.y, state);
- } else { /* handle scroll wheel event */
+ } else {
+
+ /*
+ * For scroll wheel events we need to send the XEvent here.
+ */
+
CGFloat delta;
int coarseDelta;
XEvent xEvent;
@@ -581,6 +637,56 @@ TkpWarpPointer(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * TkpSetCapture --
+ *
+ * This function captures the mouse so that all future events will be
+ * reported to this window, even if the mouse is outside the window. If
+ * the specified window is NULL, then the mouse is released.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the capture flag and captures the mouse.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpSetCapture(
+ TkWindow *winPtr) /* Capture window, or NULL. */
+{
+ while (winPtr && !Tk_IsTopLevel(winPtr)) {
+ winPtr = winPtr->parentPtr;
+ }
+ captureWinPtr = (Tk_Window) winPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetCapture --
+ *
+ * Results:
+ * Returns the current grab window
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Window
+TkMacOSXGetCapture(void)
+{
+ return captureWinPtr;
+}
+
+
+
+/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
diff --git a/macosx/tkMacOSXSend.c b/macosx/tkMacOSXSend.c
index 3b24a56..1fdf048 100644
--- a/macosx/tkMacOSXSend.c
+++ b/macosx/tkMacOSXSend.c
@@ -325,7 +325,7 @@ Tk_SendObjCmd(
int objc, /* Number of arguments */
Tcl_Obj *const objv[]) /* The arguments */
{
- const char *const sendOptions[] = {"-async", "-displayof", "-", NULL};
+ const char *const sendOptions[] = {"-async", "-displayof", "--", NULL};
char *stringRep, *destName;
/*int async = 0;*/
int i, index, firstArg;
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 7bc807a..805d58f 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -149,6 +149,7 @@ XMapWindow(
if (Tk_IsTopLevel(macWin->winPtr)) {
if (!Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *win = TkMacOSXDrawableWindow(window);
+
/*
* We want to activate Tk when a toplevel is mapped
* but we must not supply YES here. This is because
@@ -157,6 +158,7 @@ XMapWindow(
* the app to activate too early can make the menu bar
* unresponsive.
*/
+
TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
[win setExcludedFromWindowsMenu:NO];
[NSApp activateIgnoringOtherApps:NO];
@@ -166,11 +168,22 @@ XMapWindow(
} else {
[win orderFrontRegardless];
}
+
+ /*
+ * In some cases the toplevel will not be drawn unless we process
+ * all pending events now. See ticket 56a1823c73.
+ */
+
+ [NSApp _lockAutoreleasePool];
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
+ [NSApp _unlockAutoreleasePool];
} else {
+
/*
* Rebuild the container's clipping region and display
* the window.
*/
+
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
@@ -190,7 +203,9 @@ XMapWindow(
event.xmap.event = window;
event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
} else {
+
/*
* Rebuild the parent's clipping region and display the window.
*
@@ -211,11 +226,10 @@ XMapWindow(
NotifyVisibility(macWin->winPtr, &event);
/*
- * Make sure that subwindows get displayed.
+ * This seems to be needed to ensure that all subwindows get displayed.
*/
GenerateConfigureNotify(macWin->winPtr, 1);
-
}
/*
@@ -284,11 +298,7 @@ XUnmapWindow(
if (!Tk_IsEmbedded(winPtr) &&
winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
NSWindow *win = TkMacOSXDrawableWindow(window);
-
- if ([win isVisible]) {
- [[win parentWindow] removeChildWindow:win];
- [win orderOut:NSApp];
- }
+ [win orderOut:nil];
}
TkMacOSXInvalClipRgns((Tk_Window) winPtr);
@@ -1314,7 +1324,7 @@ TkMacOSXWinCGBounds(
* UpdateOffsets --
*
* Updates the X & Y offsets of the given TkWindow from the TopLevel it is
- * a decendant of.
+ * a descendant of.
*
* Results:
* None.
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index ad6af30..212381e 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -75,12 +75,10 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
if (winPtr) {
WmInfo *wmPtr = winPtr->wmInfoPtr;
NSRect bounds = [w frame];
- NSRect screenRect = [[w screen] frame];
int x, y, width = -1, height = -1, flags = 0;
- int minY = 1 + [[NSApp mainMenu] menuBarHeight];
x = bounds.origin.x;
- y = screenRect.size.height - (bounds.origin.y + bounds.size.height);
+ y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
if (winPtr->changes.x != x || winPtr->changes.y != y) {
flags |= TK_LOCATION_CHANGED;
} else {
@@ -101,20 +99,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
}
- /*
- * Mac windows cannot go higher than the bottom of the menu bar. The
- * Tk window manager can request that a window be drawn so that it
- * overlaps the menu bar, but it will actually be drawn immediately
- * below the menu bar. In such a case it saves a lot of trouble and
- * causes no harm if we let Tk think that the window is located at the
- * requested point. (Many of the the tests assume that this is the
- * case, especially for windows with upper left corner at (0,0).) So
- * we just tell a harmless white lie here.
- */
-
- if (y == minY && wmPtr->y < minY) {
- y = wmPtr->y;
- }
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
}
@@ -523,7 +507,9 @@ GenerateActivateEvents(
int activeFlag)
{
TkGenerateActivateEvents(winPtr, activeFlag);
- TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
+ if (activeFlag || ![NSApp isActive]) {
+ TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
+ }
return true;
}
@@ -680,7 +666,6 @@ TkGenWMConfigureEvent(
if (flags & TK_LOCATION_CHANGED) {
wmPtr->x = x;
wmPtr->y = y;
- //wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
}
if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index a5e1564..a1fbbde 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)
@@ -668,7 +669,7 @@ TkWmNewWindow(
wmPtr->reparent = None;
wmPtr->titleUid = NULL;
wmPtr->iconName = NULL;
- wmPtr->master = None;
+ wmPtr->master = NULL;
wmPtr->hints.flags = InputHint | StateHint;
wmPtr->hints.input = True;
wmPtr->hints.initial_state = NormalState;
@@ -678,9 +679,9 @@ TkWmNewWindow(
wmPtr->hints.icon_mask = None;
wmPtr->hints.window_group = None;
wmPtr->leaderName = NULL;
- wmPtr->masterWindowName = NULL;
wmPtr->icon = NULL;
wmPtr->iconFor = NULL;
+ wmPtr->transientPtr = NULL;
wmPtr->sizeHintsFlags = 0;
wmPtr->minWidth = wmPtr->minHeight = 1;
wmPtr->maxWidth = 0;
@@ -886,6 +887,12 @@ TkWmDeadWindow(
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);
@@ -901,9 +908,6 @@ TkWmDeadWindow(
if (wmPtr->leaderName != NULL) {
ckfree(wmPtr->leaderName);
}
- if (wmPtr->masterWindowName != NULL) {
- ckfree(wmPtr->masterWindowName);
- }
if (wmPtr->icon != NULL) {
wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
wmPtr2->iconFor = NULL;
@@ -915,7 +919,6 @@ TkWmDeadWindow(
}
while (wmPtr->protPtr != NULL) {
ProtocolHandler *protPtr = wmPtr->protPtr;
-
wmPtr->protPtr = protPtr->nextPtr;
Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
}
@@ -930,6 +933,27 @@ 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;
+ TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
+ if (masterPtr == winPtr) {
+ wmPtr2 = winPtr2->wmInfoPtr;
+ wmPtr2->master = 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
@@ -1786,6 +1810,26 @@ 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;
+ TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
+ 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;
}
@@ -2285,7 +2329,7 @@ WmIconifyCmd(
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
NULL);
return TCL_ERROR;
- } else if (wmPtr->master != None) {
+ } else if (wmPtr->master != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": it is a transient", winPtr->pathName));
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
@@ -2308,6 +2352,23 @@ 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;
+ TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
return TCL_OK;
}
@@ -3392,7 +3453,7 @@ WmStateCmd(
"OVERRIDE_REDIRECT", NULL);
return TCL_ERROR;
}
- if (wmPtr->master != None) {
+ if (wmPtr->master != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": it is a transient",
winPtr->pathName));
@@ -3507,32 +3568,29 @@ WmTransientCmd(
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
Tk_Window master;
+ TkWindow *masterPtr, *w;
WmInfo *wmPtr2;
- char *masterWindowName;
- int length;
+ Transient *transient;
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
return TCL_ERROR;
}
if (objc == 3) {
- if (wmPtr->master != None) {
+ if (wmPtr->master != NULL) {
Tcl_SetObjResult(interp,
- Tcl_NewStringObj(wmPtr->masterWindowName, -1));
+ Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
}
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;
+ masterPtr = (TkWindow*) master;
while (!Tk_TopWinHierarchy(masterPtr)) {
/*
@@ -3561,25 +3619,105 @@ WmTransientCmd(
return TCL_ERROR;
}
- if (masterPtr == winPtr) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't make \"%s\" its own master", Tk_PathName(winPtr)));
- Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
- return TCL_ERROR;
+ for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
+ w = (TkWindow *)w->wmInfoPtr->master) {
+ if (w == winPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "setting \"%s\" as master creates a transient/master cycle",
+ Tk_PathName(masterPtr)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Add the transient to the master's list, if it not already there.
+ */
+
+ for (transient = wmPtr2->transientPtr;
+ transient != NULL && transient->winPtr != winPtr;
+ transient = transient->nextPtr) {}
+ if (transient == NULL) {
+ transient = ckalloc(sizeof(Transient));
+ transient->winPtr = winPtr;
+ transient->flags = 0;
+ transient->nextPtr = wmPtr2->transientPtr;
+ wmPtr2->transientPtr = transient;
}
- wmPtr->master = Tk_WindowId(masterPtr);
- masterWindowName = masterPtr->pathName;
- length = strlen(masterWindowName);
- if (wmPtr->masterWindowName != NULL) {
- ckfree(wmPtr->masterWindowName);
+ /*
+ * 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->masterWindowName = ckalloc(length+1);
- strcpy(wmPtr->masterWindowName, masterWindowName);
+
+ wmPtr->master = (Tk_Window)masterPtr;
}
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;
+ TkWindow *masterPtr;
+ Transient *T, *temp;
+
+ if (wmPtr == NULL || wmPtr->master == NULL) {
+ return;
+ }
+ masterPtr = (TkWindow*)wmPtr->master;
+ wmPtr2 = masterPtr->wmInfoPtr;
+ if (wmPtr2 == NULL) {
+ return;
+ }
+ wmPtr->master = NULL;
+ T = wmPtr2->transientPtr;
+ while (T != NULL) {
+ if (T->winPtr != winPtr) {
+ break;
+ }
+ temp = T->nextPtr;
+ ckfree(T);
+ T = temp;
+ }
+ wmPtr2->transientPtr = T;
+ while (T != NULL) {
+ if (T->nextPtr && T->nextPtr->winPtr == winPtr) {
+ temp = T->nextPtr;
+ T->nextPtr = temp->nextPtr;
+ ckfree(temp);
+ } else {
+ T = T->nextPtr;
+ }
+ }
+}
/*
*----------------------------------------------------------------------
@@ -3620,11 +3758,27 @@ WmWithdrawCmd(
Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
return TCL_ERROR;
}
+
TkpWmSetState(winPtr, WithdrawnState);
+
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
[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;
+ TkWindow *masterPtr = (TkWindow *)TkGetTransientMaster(winPtr2);
+ if (masterPtr == winPtr &&
+ winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
+ TkpWmSetState(winPtr2, WithdrawnState);
+ transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ }
+ }
+
return TCL_OK;
}
@@ -4734,7 +4888,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;
@@ -5171,14 +5324,14 @@ TkSetWMName(
*----------------------------------------------------------------------
*/
-Window
+Tk_Window
TkGetTransientMaster(
TkWindow *winPtr)
{
if (winPtr->wmInfoPtr != NULL) {
- return winPtr->wmInfoPtr->master;
+ return (Tk_Window)winPtr->wmInfoPtr->master;
}
- return None;
+ return NULL;
}
/*
@@ -6221,8 +6374,10 @@ XSetInputFocus(
*
* TkpChangeFocus --
*
- * This procedure is a stub on the Mac because we always own the focus if
- * we are a front most application.
+ * This function is called when Tk moves focus from one window to another.
+ * It should be passed a non-embedded TopLevel. That toplevel gets raised
+ * to the top of the Tk stacking order and the associated NSWindow is
+ * ordered Front.
*
* Results:
* The return value is the serial number of the command that changed the
@@ -6413,7 +6568,7 @@ TkMacOSXApplyWindowAttributes(
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
- if (wmPtr->master != None || winPtr->atts.override_redirect) {
+ if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
ApplyMasterOverrideChanges(winPtr, macWindow);
}
}
@@ -6550,7 +6705,7 @@ ApplyWindowAttributeFlagChanges(
*/
if ((winPtr->atts.override_redirect) ||
- (wmPtr->master != None) ||
+ (wmPtr->master != NULL) ||
(winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
NSWindowCollectionBehaviorFullScreenAuxiliary);
@@ -6627,6 +6782,7 @@ ApplyMasterOverrideChanges(
int oldFlags = wmPtr->flags;
unsigned long styleMask;
NSRect structureRect;
+ NSWindow *parentWindow;
if (!macWindow && winPtr->window != None &&
TkMacOSXHostToplevelExists(winPtr)) {
@@ -6667,7 +6823,6 @@ ApplyMasterOverrideChanges(
}
}
if (macWindow) {
- NSWindow *parentWindow = [macWindow parentWindow];
structureRect = [NSWindow frameRectForContentRect:NSZeroRect
styleMask:styleMask];
@@ -6686,7 +6841,7 @@ ApplyMasterOverrideChanges(
if (wmPtr->hints.initial_state == NormalState) {
[macWindow orderFront:nil];
}
- if (wmPtr->master != None) {
+ if (wmPtr->master != NULL) {
wmPtr->flags |= WM_TOPMOST;
} else {
wmPtr->flags &= ~WM_TOPMOST;
@@ -6702,29 +6857,47 @@ ApplyMasterOverrideChanges(
wmPtr->flags &= ~WM_TOPMOST;
}
if (wmPtr->master != None) {
- TkDisplay *dispPtr = TkGetDisplayList();
- TkWindow *masterWinPtr = (TkWindow *)
- Tk_IdToWindow(dispPtr->display, wmPtr->master);
-
+ TkWindow *masterWinPtr = (TkWindow *)wmPtr->master;
if (masterWinPtr && masterWinPtr->window != None &&
TkMacOSXHostToplevelExists(masterWinPtr)) {
- NSWindow *masterMacWin =
- TkMacOSXDrawableWindow(masterWinPtr->window);
+ NSWindow *masterMacWin = TkMacOSXDrawableWindow(
+ masterWinPtr->window);
- if (masterMacWin && masterMacWin != parentWindow &&
- (winPtr->flags & TK_MAPPED)) {
- if (parentWindow) {
+ /*
+ * Try to add the transient window as a child window of the
+ * master. A child NSWindow retains its relative position with
+ * respect to the parent when the parent is moved. This is
+ * pointless if the parent is offscreen, and adding a child to
+ * an offscreen window causes the parent to be displayed as a
+ * zombie. So we only do this if the parent is visible.
+ */
+
+ if (masterMacWin &&
+ [masterMacWin isVisible] &&
+ (winPtr->flags & TK_MAPPED)) {
+
+ /*
+ * If the transient is already a child of some other window,
+ * remove it.
+ */
+
+ parentWindow = [macWindow parentWindow];
+ if (parentWindow && parentWindow != masterMacWin) {
[parentWindow removeChildWindow:macWindow];
}
+
[masterMacWin addChildWindow:macWindow
- ordered:NSWindowAbove];
- if (wmPtr->flags & WM_TOPMOST) {
- [macWindow setLevel:kCGUtilityWindowLevel];
+ ordered:NSWindowAbove];
}
- }
}
- } else if (parentWindow) {
- [parentWindow removeChildWindow:macWindow];
+ } else {
+ parentWindow = [macWindow parentWindow];
+ if (parentWindow) {
+ [parentWindow removeChildWindow:macWindow];
+ }
+ }
+ if (wmPtr->flags & WM_TOPMOST) {
+ [macWindow setLevel:kCGUtilityWindowLevel];
}
ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes,
oldFlags, 0, 0);
diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h
index 43f1a7a..5f07fe6 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
@@ -54,7 +65,7 @@ typedef struct TkWmInfo {
Tk_Uid titleUid; /* Title to display in window caption. If NULL,
* use name of widget. */
char *iconName; /* Name to display in icon. */
- Window master; /* Master window for TRANSIENT_FOR property, or
+ Tk_Window master; /* Master window for TRANSIENT_FOR property, or
* None. */
XWMHints hints; /* Various pieces of information for window
* manager. */
@@ -62,14 +73,13 @@ typedef struct TkWmInfo {
* (corresponds to hints.window_group).
* Malloc-ed. Note: this field doesn't get
* updated if leader is destroyed. */
- char *masterWindowName; /* Path name of window specified as master in
- * "wm transient" command, or NULL. Malloc-ed.
- * Note: this field doesn't get updated if
- * masterWindowName is destroyed. */
Tk_Window icon; /* Window to use as icon for this window, or
* 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
diff --git a/tests/imgPhoto.test b/tests/imgPhoto.test
index 97fb7ae..c45c5fb 100644
--- a/tests/imgPhoto.test
+++ b/tests/imgPhoto.test
@@ -1212,6 +1212,39 @@ test imgPhoto-14.5 {Bug [fbaed1f66b] - GIF decoder with deferred clear code} -se
image create photo -file $fileName -format "gif -index 2"
} -returnCodes error -result {no image data for this index}
+test imgPhoto-14.6 {Access Subimage after Subimage with buffer overflow. Ticket 4da2191b} -setup {
+ set data {
+ R0lGODlhYwA5APcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgAysnGy8hKzM
+ hASs3MTcjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwP8AAAD/
+ AP//AAAA//8A/wD//////ywAAAAAYwA5AAAI/wAZCBxIsKDBgwgTKlzIsKHD
+ hxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN
+ mzhz6tzJs6fPn0CDCh1KtKhRiwoSKEXAtGlTpUqPGkyagOmCq1edNsWalWkC
+ BUSXIuDqFepBqFWtZv3KU+zYrkrBSqT6dgECtjOTbu16NwFHvV3lshRLti/J
+ qlgRCE6ZuO9ik4Dt+k0ZVyZiyVIvXr77ODPEy5g9T4zMWfTEzXdNz1VbWvXn
+ uqldP1TAOrbshqBb314Y2W7n3Qdpv7UNPCHpycUVbv6dnODy5sqzQldIe8H0
+ hciva9/Ovbv37+BzBgE7ACH5BAFkAAMALAAAAAAEAAQAAAMEKLrckgA7
+ }
+} -body {
+ image create photo photo1 -data $data -format "GIF -index 1"
+} -cleanup {
+ catch {image delete photo1}
+} -result photo1
+
test imgPhoto-15.1 {photo images can fail to allocate memory gracefully} -constraints {
nonPortable
} -body {
diff --git a/tests/menu.test b/tests/menu.test
index 95699ff..9ad2a0c 100644
--- a/tests/menu.test
+++ b/tests/menu.test
@@ -1606,7 +1606,7 @@ test menu-3.47 {MenuWidgetCmd procedure, "post" option} -setup {
.m1 post
} -cleanup {
destroy .m1
-} -returnCodes error -result {wrong # args: should be ".m1 post x y"}
+} -returnCodes error -result {wrong # args: should be ".m1 post x y ?index?"}
test menu-3.48 {MenuWidgetCmd procedure, "post" option} -setup {
destroy .m1
} -body {
diff --git a/tests/menubut.test b/tests/menubut.test
index 6efdb0f..88f4330 100644
--- a/tests/menubut.test
+++ b/tests/menubut.test
@@ -542,7 +542,11 @@ test menubutton-6.1 {MenuButtonCmdDeletedProc procedure} -setup {
deleteWindows
} -result {{} {}}
-
+if {[tk windowingsystem] == "aqua"} {
+ set extraWidth 36
+} else {
+ set extraWidth 0
+}
test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
testImageType
} -setup {
@@ -555,33 +559,33 @@ test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
} -cleanup {
deleteWindows
imageCleanup
-} -result {38 23}
+} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {
testImageType
} -setup {
deleteWindows
image create test image1
} -body {
- menubutton .mb -image image1 -bd 1 -highlightthickness 2
+ menubutton .mb -image image1 -bd 3 -highlightthickness 1
pack .mb
list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
deleteWindows
imageCleanup
-} -result {36 21}
+} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.3 {ComputeMenuButtonGeometry procedure} -constraints {
testImageType
} -setup {
deleteWindows
image create test image1
} -body {
- menubutton .mb -image image1 -bd 0 -highlightthickness 2 -padx 5 -pady 5
+ menubutton .mb -image image1 -bd 1 -highlightthickness 3 -padx 5 -pady 5
pack .mb
list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
deleteWindows
imageCleanup
-} -result {34 19}
+} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
testImageType
} -setup {
@@ -595,7 +599,7 @@ test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
} -cleanup {
deleteWindows
imageCleanup
-} -result {48 23}
+} -result [list [expr {48 + $extraWidth}] 23]
test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
testImageType
} -setup {
@@ -609,7 +613,7 @@ test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
} -cleanup {
deleteWindows
imageCleanup
-} -result {38 38}
+} -result [list [expr {38 + $extraWidth}] 38]
test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
deleteWindows
} -body {
@@ -619,7 +623,7 @@ test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
deleteWindows
-} -result {25 35}
+} -result [list [expr {25 + $extraWidth}] 35]
test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
deleteWindows
} -body {
@@ -629,7 +633,7 @@ test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
deleteWindows
-} -result {46 33}
+} -result [list [expr {46 + $extraWidth}] 33]
test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
deleteWindows
} -body {
@@ -639,7 +643,7 @@ test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
deleteWindows
-} -result {23 56}
+} -result [list [expr {23 + $extraWidth}] 56]
test menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {
fonts
} -setup {
diff --git a/tests/scale.test b/tests/scale.test
index 79524eb..7fa3a62 100644
--- a/tests/scale.test
+++ b/tests/scale.test
@@ -1104,78 +1104,78 @@ test scale-13.6 {SetScaleValue procedure} -body {
destroy .s
pack [scale .s]
update
-test scale-14.1 {RoundToResolution procedure} -body {
+test scale-14.1 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 84 152
} -result 72
-test scale-14.2 {RoundToResolution procedure} -body {
+test scale-14.2 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 100 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 86 152
} -result 76
-test scale-14.3 {RoundToResolution procedure} -body {
+test scale-14.3 {RoundValueToResolution procedure} -body {
.s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 84 152
} -result 28
-test scale-14.4 {RoundToResolution procedure} -body {
+test scale-14.4 {RoundValueToResolution procedure} -body {
.s configure -from 100 -to 0 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 86 152
} -result 24
-test scale-14.5 {RoundToResolution procedure} -body {
+test scale-14.5 {RoundValueToResolution procedure} -body {
.s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 84 152
} -result {-28}
-test scale-14.6 {RoundToResolution procedure} -body {
+test scale-14.6 {RoundValueToResolution procedure} -body {
.s configure -from -100 -to 0 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 86 152
} -result {-24}
-test scale-14.7 {RoundToResolution procedure} -body {
+test scale-14.7 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 84 152
} -result {-72}
-test scale-14.8 {RoundToResolution procedure} -body {
+test scale-14.8 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to -100 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 4.0
update
.s get 86 152
} -result {-76}
-test scale-14.9 {RoundToResolution procedure} -body {
+test scale-14.9 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 2.25 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 0
update
.s get 84 152
} -result {1.64}
-test scale-14.10 {RoundToResolution procedure} -body {
+test scale-14.10 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 2.25 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 0
update
.s get 86 152
} -result {1.69}
-test scale-14.11 {RoundToResolution procedure} -body {
+test scale-14.11 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 0 -digits 5
update
.s get 84 152
} -result {164.25}
-test scale-14.12 {RoundToResolution procedure} -body {
+test scale-14.12 {RoundValueToResolution procedure} -body {
.s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
-orient horizontal -resolution 0 -digits 5
update
@@ -1183,6 +1183,41 @@ test scale-14.12 {RoundToResolution procedure} -body {
} -result {168.75}
destroy .s
+test scale-14.13 {RoundValueToResolution procedure, round-off errors} -setup {
+ # see [220665ffff], and duplicates [220265ffff] and [779559ffff]
+ set x NotSet
+ pack [scale .s -orient horizontal -resolution .1 -from -180 -to 180 -command "set x"]
+ update
+} -body {
+ .s configure -background red
+ update
+ set x
+} -cleanup {
+ destroy .s
+} -result {NotSet}
+
+test scale-14a.1 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {
+ pack [scale .s -orient horizontal]
+ update
+} -body {
+ .s configure -length 400 -bd 0 -from 1 -to 9 -resolution 2 -tickinterval 1
+ update
+ .s get 200 0
+} -cleanup {
+ destroy .s
+} -result {5}
+test scale-14a.2 {RoundValueToResolution, RoundIntervalToResolution procedures} -setup {
+ pack [scale .s -orient horizontal]
+ update
+} -body {
+ .s configure -length 400 -bd 0 -from -1.5 -to 1.5 -resolution 1 \
+ -tickinterval 1 -digits 2
+ update
+ .s get 250 0
+} -cleanup {
+ destroy .s
+} -result {0.5}
+
test scale-15.1 {ScaleVarProc procedure} -setup {
deleteWindows
diff --git a/tests/send.test b/tests/send.test
index 945d4d0..403a207 100644
--- a/tests/send.test
+++ b/tests/send.test
@@ -197,7 +197,8 @@ test send-7.4 {Tk_SetAppName procedure, name in use} {secureserver testsend} {
list [tk appname foo] [testsend prop root InterpRegistry]
} "{foo #4} {$commId foo #4\n$id foo\n$id foo #2\n$id foo #3\n}"
-test send-8.1 {Tk_SendCmd procedure, options} {secureserver} {
+#macOS does not send to other processes
+test send-8.1 {Tk_SendCmd procedure, options} {secureserver notAqua} {
setupbg
set app [dobg {tk appname}]
set a 66
@@ -222,10 +223,11 @@ test send-8.2 {Tk_SendCmd procedure, options} {secureserver altDisplay} {
cleanupbg
set result
} {altDisplay homeDisplay}
-test send-8.3 {Tk_SendCmd procedure, options} {secureserver} {
+# Since macOS has no registry of interpreters, 8.3, 8.4 and 8.10 will fail.
+test send-8.3 {Tk_SendCmd procedure, options} {secureserver notAqua} {
list [catch {send -- -async foo bar baz} msg] $msg
} {1 {no application named "-async"}}
-test send-8.4 {Tk_SendCmd procedure, options} {secureserver} {
+test send-8.4 {Tk_SendCmd procedure, options} {secureserver notAqua} {
list [catch {send -gorp foo bar baz} msg] $msg
} {1 {no application named "-gorp"}}
test send-8.5 {Tk_SendCmd procedure, options} {secureserver} {
@@ -253,7 +255,7 @@ test send-8.9 {Tk_SendCmd procedure, local execution} {secureserver} {
"open bad_file"
invoked from within
"send [tk appname] open bad_file"} {posix enoent {no such file or directory}}}
-test send-8.10 {Tk_SendCmd procedure, no such interpreter} {secureserver} {
+test send-8.10 {Tk_SendCmd procedure, no such interpreter} {secureserver notAqua} {
list [catch {send bogus_name bogus_command} msg] $msg
} {1 {no application named "bogus_name"}}
@@ -542,7 +544,8 @@ test send-12.1 {TimeoutProc procedure} {secureserver testsend} {
catch {testsend prop root InterpRegistry ""}
-test send-12.2 {TimeoutProc procedure} {secureserver} {
+#macOS does not send to other processes
+test send-12.2 {TimeoutProc procedure} {secureserver notAqua} {
winfo interps
tk appname tktest
update
@@ -557,16 +560,17 @@ test send-12.2 {TimeoutProc procedure} {secureserver} {
set result
} {1 {target application died}}
+#macOS does not send to other processes
winfo interps
tk appname tktest
-test send-13.1 {DeleteProc procedure} {secureserver} {
+test send-13.1 {DeleteProc procedure} {secureserver notAqua} {
setupbg
set app [dobg {rename send {}; tk appname}]
set result [list [catch {send $app foo} msg] $msg [winfo interps]]
cleanupbg
set result
} {1 {no application named "tktest #2"} tktest}
-test send-13.2 {DeleteProc procedure} {secureserver} {
+test send-13.2 {DeleteProc procedure} {secureserver notAqua} {
winfo interps
tk appname tktest
rename send {}
diff --git a/tests/text.test b/tests/text.test
index aaddc2c..be25ca6 100644
--- a/tests/text.test
+++ b/tests/text.test
@@ -3474,6 +3474,12 @@ test text-14.18 {ConfigureText procedure} -constraints fonts -setup {
# minimum size and it was interfering with the size requested by the -setgrid.
# The "overrideredirect" gets rid of the titlebar so the toplevel can shrink
# to the appropriate size.
+# On macOS, however, there is no way to make the window overlap the menubar.
+if {[tk windowingsystem] == "aqua"} {
+ set minY 23
+} else {
+ set minY 0
+}
test text-14.19 {ConfigureText procedure} -setup {
toplevel .top
text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
@@ -3481,16 +3487,17 @@ test text-14.19 {ConfigureText procedure} -setup {
.top.t configure -width 20 -height 10 -setgrid 1
wm overrideredirect .top 1
pack .top.t
- wm geometry .top +0+0
+ wm geometry .top +0+$minY
update
wm geometry .top
} -cleanup {
destroy .top
-} -result {20x10+0+0}
+} -result "20x10+0+$minY"
# This test was failing on Windows because the title bar on .t was a certain
# minimum size and it was interfering with the size requested by the -setgrid.
# The "overrideredirect" gets rid of the titlebar so the toplevel can shrink
# to the appropriate size.
+# On macOS we again use minY as a workaround.
test text-14.20 {ConfigureText procedure} -setup {
toplevel .top
text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
@@ -3498,7 +3505,7 @@ test text-14.20 {ConfigureText procedure} -setup {
.top.t configure -width 20 -height 10 -setgrid 1
wm overrideredirect .top 1
pack .top.t
- wm geometry .top +0+0
+ wm geometry .top +0+$minY
update
set result [wm geometry .top]
wm geometry .top 15x8
@@ -3509,7 +3516,7 @@ test text-14.20 {ConfigureText procedure} -setup {
lappend result [wm geometry .top]
} -cleanup {
destroy .top
-} -result {20x10+0+0 15x8+0+0 15x8+0+0}
+} -result "20x10+0+$minY 15x8+0+$minY 15x8+0+$minY"
test text-15.1 {TextWorldChanged procedure, spacing options} -constraints {
diff --git a/tests/unixButton.test b/tests/unixButton.test
index 137ef33..325f497 100644
--- a/tests/unixButton.test
+++ b/tests/unixButton.test
@@ -35,7 +35,15 @@ proc bogusTrace args {
error "trace aborted"
}
-
+if {[tk windowingsystem] eq "aqua"} {
+ set smallIndicator 20
+ set bigIndicator 20
+ set defaultBorder 10
+} else {
+ set smallIndicator 27
+ set bigIndicator 40
+ set defaultBorder 20
+}
test unixbutton-1.1 {TkpComputeButtonGeometry procedure} -constraints {
unix testImageType
} -setup {
@@ -57,7 +65,10 @@ test unixbutton-1.1 {TkpComputeButtonGeometry procedure} -constraints {
} -cleanup {
deleteWindows
image delete image1
-} -result {68 48 74 54 112 52 112 52}
+} -result [list 68 48 \
+ 74 54 \
+ [expr {72 + $bigIndicator}] 52 \
+ [expr {72 + $bigIndicator}] 52]
test unixbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {
unix
} -setup {
@@ -75,7 +86,10 @@ test unixbutton-1.2 {TkpComputeButtonGeometry procedure} -constraints {
[winfo reqwidth .b4] [winfo reqheight .b4]
} -cleanup {
deleteWindows
-} -result {23 33 29 39 54 37 54 37}
+} -result [list 23 33 \
+ 29 39 \
+ [expr {27 + $smallIndicator}] 37 \
+ [expr {27 + $smallIndicator}] 37]
test unixbutton-1.3 {TkpComputeButtonGeometry procedure} -constraints {
unix
} -setup {
@@ -186,7 +200,7 @@ test unixbutton-1.9 {TkpComputeButtonGeometry procedure} -constraints {
list [winfo reqwidth .b2] [winfo reqheight .b2]
} -cleanup {
deleteWindows
-} -result {37 47}
+} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
test unixbutton-1.10 {TkpComputeButtonGeometry procedure} -constraints {
unix
} -setup {
@@ -196,7 +210,7 @@ test unixbutton-1.10 {TkpComputeButtonGeometry procedure} -constraints {
list [winfo reqwidth .b2] [winfo reqheight .b2]
} -cleanup {
deleteWindows
-} -result {37 47}
+} -result [list [expr {17 + $defaultBorder}] [expr {27 + $defaultBorder}]]
test unixbutton-1.11 {TkpComputeButtonGeometry procedure} -constraints {
unix
} -setup {
diff --git a/tests/unixEmbed.test b/tests/unixEmbed.test
index 8aaa3c4..99f7265 100644
--- a/tests/unixEmbed.test
+++ b/tests/unixEmbed.test
@@ -1,4 +1,4 @@
-# This file is a Tcl script to test out the procedures in the file
+# This file is a Tcl script to test out the procedures in the file
# tkUnixEmbed.c. It is organized in the standard fashion for Tcl
# tests.
#
@@ -11,6 +11,37 @@ eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test
+namespace eval ::_test_tmp {}
+
+# ------------------------------------------------------------------------------
+# Proc ::_test_tmp::testInterp
+# ------------------------------------------------------------------------------
+# Command that creates an unsafe child interpreter and tries to load Tk.
+# This code is borrowed from safePrimarySelection.test
+# This is necessary for loading Tktest if the tests are done in the build
+# directory without installing Tk. In that case the usual auto_path loading
+# mechanism cannot work because the tk binary is not where pkgIndex.tcl says
+# it is.
+# ------------------------------------------------------------------------------
+
+namespace eval ::_test_tmp {
+ variable TkLoadCmd
+}
+
+foreach pkg [info loaded] {
+ if {[lindex $pkg 1] eq "Tk"} {
+ set ::_test_tmp::TkLoadCmd [list load {*}$pkg]
+ break
+ }
+}
+
+proc ::_test_tmp::testInterp {name} {
+ variable TkLoadCmd
+ interp create $name
+ $name eval [list set argv [list -name $name]]
+ catch {{*}$TkLoadCmd $name}
+}
+
setupbg
dobg {wm withdraw .}
@@ -55,14 +86,14 @@ proc colorsFree {w {red 31} {green 245} {blue 192}} {
}
test unixEmbed-1.1 {TkpUseWindow procedure, bad window identifier} -constraints {
- unix
+ unix
} -setup {
deleteWindows
} -body {
toplevel .t -use xyz
} -returnCodes error -result {expected integer but got "xyz"}
test unixEmbed-1.2 {TkpUseWindow procedure, bad window identifier} -constraints {
- unix
+ unix
} -setup {
deleteWindows
} -body {
@@ -97,7 +128,7 @@ test unixEmbed-1.4 {TkpUseWindow procedure, inheriting colormap} -constraints {
} -result {1}
test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -113,8 +144,29 @@ test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constra
} -cleanup {
deleteWindows
} -result {{{XXX {} {} .t}} 0}
+test unixEmbed-1.5a {TkpUseWindow procedure, creating Container records} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ frame .f2 -container 1 -width 200 -height 50
+ pack .f1 .f2
+ slave alias w winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t -use [w]
+ list [testembed] [expr {[lindex [lindex [testembed all] 0] 0] - [w]}]
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{{XXX {} {} .t}} 0}
test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -132,6 +184,29 @@ test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constra
} -cleanup {
deleteWindows
} -result {{XXX {} {} .t2} {XXX {} {} .t1}}
+test unixEmbed-1.6a {TkpUseWindow procedure, creating Container records} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ frame .f2 -container 1 -width 200 -height 50
+ pack .f1 .f2
+ slave alias w1 winfo id .f1
+ slave alias w2 winfo id .f2
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ toplevel .t2 -use [w2]
+ testembed
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{XXX {} {} .t2} {XXX {} {} .t1}}
test unixEmbed-1.7 {TkpUseWindow procedure, container and embedded in same app} -constraints {
unix testembed
} -setup {
@@ -152,7 +227,7 @@ test unixEmbed-1.7 {TkpUseWindow procedure, container and embedded in same app}
test unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -172,8 +247,32 @@ test unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {
} -cleanup {
deleteWindows
} -result {}
+test unixEmbed-2.1a {EmbeddedEventProc procedure} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ testembed
+ }
+ destroy .f1
+ update
+ slave eval {
+ testembed
+ }
+} -cleanup {
+ deleteWindows
+} -result {}
test unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -190,8 +289,30 @@ test unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {
} -cleanup {
deleteWindows
} -result {}
+test unixEmbed-2.2a {EmbeddedEventProc procedure} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ testembed
+ destroy .t1
+ testembed
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {}
test unixEmbed-2.3 {EmbeddedEventProc procedure} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -207,21 +328,20 @@ test unixEmbed-2.4 {EmbeddedEventProc procedure} -constraints {
} -setup {
deleteWindows
} -body {
- frame .f1 -container 1 -width 200 -height 50
- pack .f1
+ pack [frame .f1 -container 1 -width 200 -height 50]
toplevel .t1 -use [winfo id .f1]
+ set x [testembed]
update
destroy .t1
- set x [testembed]
update
- list $x [testembed]
+ list $x [winfo exists .t1] [winfo exists .f1] [testembed]
} -cleanup {
deleteWindows
-} -result {{{XXX .f1 {} {}}} {}}
+} -result "{{XXX .f1 {} .t1}} 0 0 {}"
test unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints {
- unix testembed nonPortable
+ unix testembed notPortable
} -body {
frame .f1 -container 1 -width 200 -height 50
pack .f1
@@ -236,10 +356,32 @@ test unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints
} -cleanup {
deleteWindows
} -result {{{XXX .f1 {} {}}} {{XXX .f1 XXX {}}}}
+test unixEmbed-3.1a {ContainerEventProc procedure, detect creation} -constraints {
+ unix testembed
+} -setup {
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ set x [testembed]
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ wm withdraw .t1
+ }
+ list $x [testembed]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{{XXX .f1 {} {}}} {{XXX .f1 {} {}}}}
test unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constraints {
- unix
+ unix
} -setup {
deleteWindows
+ update
} -body {
toplevel .t1 -container 1
wm geometry .t1 +0+0
@@ -250,7 +392,7 @@ test unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constra
deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -270,8 +412,31 @@ test unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -co
} -cleanup {
deleteWindows
} -result {200x200+0+0}
+test unixEmbed-3.3a {ContainerEventProc procedure, disallow position changes} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1] -bd 2 -relief raised
+ update
+ wm geometry .t1 +30+40
+ update
+ wm geometry .t1
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {200x200+0+0}
test unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -291,8 +456,31 @@ test unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -co
} -cleanup {
deleteWindows
} -result {300x100+0+0}
+test unixEmbed-3.4a {ContainerEventProc procedure, disallow position changes} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ wm geometry .t1 300x100+30+40
+ update
+ wm geometry .t1
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {300x100+0+0}
test unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -312,8 +500,30 @@ test unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraint
} -cleanup {
deleteWindows
} -result {300 80 300x80+0+0}
+test unixEmbed-3.5a {ContainerEventProc procedure, geometry requests} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ .t1 configure -width 300 -height 80
+ update
+ }
+ list [winfo width .f1] [winfo height .f1] [slave eval {wm geometry .t1}]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {300 80 300x80+0+0}
test unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -335,8 +545,33 @@ test unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {
} -cleanup {
deleteWindows
} -result {mapped}
+test unixEmbed-3.6a {ContainerEventProc procedure, map requests} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ set x unmapped
+ bind .t1 <Map> {set x mapped}
+ update
+ after 100
+ update
+ set x
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {mapped}
test unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -358,10 +593,34 @@ test unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {
} -cleanup {
deleteWindows
} -result {dead 0}
-
+test unixEmbed-3.7a {ContainerEventProc procedure, destroy events} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ bind .f1 <Destroy> {set x dead}
+ set x alive
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ destroy .t1
+ }
+ update
+ list $x [winfo exists .f1]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {dead 0}
test unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -383,8 +642,31 @@ test unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints
} -cleanup {
deleteWindows
} -result {180x100+0+0}
+test unixEmbed-4.1a {EmbedStructureProc procedure, configure events} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ .t1 configure -width 180 -height 100
+ update
+ winfo geometry .t1
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {180x100+0+0}
test unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
@@ -398,14 +680,38 @@ test unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {
update
set x [testembed]
destroy .f1
+ update
list $x [testembed]
} -cleanup {
deleteWindows
} -result {{{XXX .f1 XXX {}}} {}}
+test unixEmbed-4.2a {EmbedStructureProc procedure, destroy events} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ update
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ }
+ set x [testembed]
+ destroy .f1
+ list $x [testembed]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result "{{XXX .f1 {} {}}} {}"
test unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -425,8 +731,34 @@ test unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {
} -cleanup {
deleteWindows
} -result {{focus in .t1}}
+test unixEmbed-5.1a {EmbedFocusProc procedure, FocusIn events} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ bind .t1 <FocusIn> {lappend x "focus in %W"}
+ bind .t1 <FocusOut> {lappend x "focus out %W"}
+ update
+ set x {}
+ }
+ focus -force .f1
+ update
+ slave eval {set x}
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{focus in .t1}}
test unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -447,8 +779,32 @@ test unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constrai
} -cleanup {
deleteWindows
} -result {}
+test unixEmbed-5.2a {EmbedFocusProc procedure, focusing on dead window} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ after 200 {destroy .t1}
+ }
+ after 400
+ focus -force .f1
+ update
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {}
test unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -471,10 +827,39 @@ test unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {
} -cleanup {
deleteWindows
} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}
+test unixEmbed-5.3a {EmbedFocusProc procedure, FocusOut events} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ set x {}
+ bind .t1 <FocusIn> {lappend x "focus in %W"}
+ bind .t1 <FocusOut> {lappend x "focus out %W"}
+ update
+ }
+ focus -force .f1
+ update
+ set x [slave eval {update; set x }]
+ focus .
+ update
+ list $x [slave eval {update; set x}]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}
test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -484,9 +869,7 @@ test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constr
dobg {
eval destroy [winfo child .]
toplevel .t1 -use $w1
- }
- update
- dobg {
+ update
bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
set x {}
.t1 configure -width 300 -height 120
@@ -496,8 +879,33 @@ test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constr
} -cleanup {
deleteWindows
} -result {{{configure .t1 300 120}} 300x120+0+0}
+test unixEmbed-6.1a {EmbedGeometryRequest procedure, window changes size} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ bind .t1 <Configure> {set x {configure .t1 %w %h}}
+ set x {}
+ .t1 configure -width 300 -height 120
+ update
+ list $x [winfo geom .t1]
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{configure .t1 300 120} 300x120+0+0}
test unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -507,25 +915,47 @@ test unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constr
dobg {
eval destroy [winfo child .]
toplevel .t1 -use $w1
- }
- after 300 {set x done}
- vwait x
- dobg {
+ update
bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
set x {}
.t1 configure -width 300 -height 120
- update
+ update
list $x [winfo geom .t1]
}
} -cleanup {
deleteWindows
} -result {{{configure .t1 200 200}} 200x200+0+0}
+test unixEmbed-6.2a {EmbedGeometryRequest procedure, window changes size} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ place .f1 -width 200 -height 200
+ update
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ update
+ bind .t1 <Configure> {set x {configure .t1 %w %h}}
+ set x {}
+ .t1 configure -width 300 -height 120
+ update
+ list $x [winfo geom .t1]
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{configure .t1 200 200} 200x200+0+0}
# Can't think up any tests for TkpGetOtherWindow procedure.
-
test unixEmbed-7.1 {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -553,8 +983,41 @@ test unixEmbed-7.1 {TkpRedirectKeyEvent procedure, forward keystroke} -constrain
deleteWindows
bind . <KeyPress> {}
} -result {{{key a 1}} {}}
+test unixEmbed-7.1a {TkpRedirectKeyEvent procedure, forward keystroke} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ deleteWindows
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ }
+ focus -force .
+ bind . <KeyPress> {lappend x {key %A %E}}
+ set x {}
+ set y [slave eval {
+ update
+ bind .t1 <KeyPress> {lappend y {key %A}}
+ set y {}
+ event generate .t1 <KeyPress> -keysym a
+ set y
+ }]
+ update
+ list $x $y
+} -cleanup {
+ interp delete slave
+ deleteWindows
+ bind . <KeyPress> {}
+} -result {{{key a 1}} {}}
test unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
- unix
+ unix notAqua
} -setup {
deleteWindows
} -body {
@@ -583,9 +1046,44 @@ test unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width
deleteWindows
bind . <KeyPress> {}
} -result {{} {{key b}}}
+test unixEmbed-7.2a {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
+ unix
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1]
+ }
+ update
+ focus -force .f1
+ update
+ bind . <KeyPress> {lappend x {key %A}}
+ set x {}
+ set y [slave eval {
+ update
+ bind .t1 <KeyPress> {lappend y {key %A}}
+ set y {}
+ event generate .t1 <KeyPress> -keysym b
+ set y
+ }]
+ update
+ list $x $y
+} -cleanup {
+ interp delete slave
+ deleteWindows
+ bind . <KeyPress> {}
+} -result {{} {{key b}}}
-
-test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints unix -setup {
+test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints {
+ unix notAqua
+} -setup {
deleteWindows
} -body {
frame .f1 -container 1 -width 200 -height 50
@@ -609,15 +1107,44 @@ test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints unix -setup {
} -cleanup {
deleteWindows
} -result {{{} .t1} .f1}
-test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
- deleteWindows
- catch {interp delete child}
+test unixEmbed-8.1a {TkpClaimFocus procedure} -constraints unix -setup {
deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
} -body {
frame .f1 -container 1 -width 200 -height 50
frame .f2 -width 200 -height 50
pack .f1 .f2
+ update
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
+ }
+ # This should clear focus from the application embedded in .f1
+ focus -force .f2
+ update
+ list [slave eval {
+ set x [list [focus]]
+ focus .t1
+ update
+ lappend x [focus]
+ }] [focus]
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{{} .t1} .f1}
+test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
+ deleteWindows
+ catch {interp delete child}
interp create child
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ frame .f2 -width 200 -height 50
+ pack .f1 .f2
+ update
+ set w1 [winfo id .f1]
child eval "set argv {-use [winfo id .f1]}"
load {} Tk child
child eval {
@@ -636,7 +1163,6 @@ test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
} -result {{{} .} .f1}
catch {interp delete child}
-
test unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints {
unix testembed
} -setup {
@@ -658,12 +1184,13 @@ test unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints
deleteWindows
} -result {{{XXX .f4 {} {}} {XXX .f3 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f4 {} {}} {XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}} {XXX .f1 {} {}}} {{XXX .f2 {} {}}} {}}
test unixEmbed-9.2 {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
- unix testembed
+ unix testembed notAqua
} -setup {
deleteWindows
} -body {
frame .f1 -container 1 -width 200 -height 50
pack .f1
+ update
dobg "set w1 [winfo id .f1]"
dobg {
eval destroy [winfo child .]
@@ -676,15 +1203,39 @@ test unixEmbed-9.2 {EmbedWindowDeleted procedure, check embeddedPtr} -constraint
} -cleanup {
deleteWindows
} -result {{{XXX {} {} .t1}} {}}
+test unixEmbed-9.2a {EmbedWindowDeleted procedure, check embeddedPtr} -constraints {
+ unix testembed
+} -setup {
+ deleteWindows
+ catch {interp delete slave}
+ ::_test_tmp::testInterp slave
+ load {} Tktest slave
+} -body {
+ frame .f1 -container 1 -width 200 -height 50
+ pack .f1
+ slave alias w1 winfo id .f1
+ slave eval {
+ destroy [winfo child .]
+ toplevel .t1 -use [w1] -highlightthickness 2 -bd 2 -relief sunken
+ set x {}
+ lappend x [testembed]
+ destroy .t1
+ lappend x [testembed]
+ }
+} -cleanup {
+ interp delete slave
+ deleteWindows
+} -result {{{XXX {} {} .t1}} {}}
test unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
- unix
+ unix
} -setup {
deleteWindows
} -body {
frame .f1 -container 1 -width 200 -height 50
pack .f1
+ update
toplevel .t1 -use [winfo id .f1] -width 150 -height 80
update
wm geometry .t1 +40+50
@@ -694,7 +1245,7 @@ test unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -con
deleteWindows
} -result {150x80+0+0}
test unixEmbed-10.2 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
- unix
+ unix
} -setup {
deleteWindows
} -body {
@@ -714,4 +1265,3 @@ deleteWindows
cleanupbg
cleanupTests
return
-
diff --git a/tests/unixWm.test b/tests/unixWm.test
index 12a2142..c147bbf 100644
--- a/tests/unixWm.test
+++ b/tests/unixWm.test
@@ -40,8 +40,23 @@ proc makeToplevels {} {
}
}
+# On macOS windows are not allowed to overlap the menubar at the top
+# of the screen. So tests which move a window and then check whether
+# it got moved to the requested location should use a y coordinate
+# larger than the height of the menubar (normally 23 pixels).
+
+if {[tk windowingsystem] eq "aqua"} {
+ set Y0 23
+ set Y2 25
+ set Y5 28
+} else {
+ set Y0 0
+ set Y2 2
+ set Y5 5
+}
+
set i 1
-foreach geom {+20+80 +80+20 +0+0} {
+foreach geom "+23+80 +80+23 +0+$Y0" {
destroy .t
test unixWm-1.$i {initial window position} unix {
toplevel .t -width 200 -height 150
@@ -67,7 +82,7 @@ update
scan [wm geom .t] %dx%d+%d+%d width height x y
set xerr [expr 150-$x]
set yerr [expr 150-$y]
-foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
+foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
test unixWm-2.$i {moving window while mapped} unix {
wm geom .t $geom
update
@@ -79,7 +94,7 @@ foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
}
set i 1
-foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
+foreach geom "+20+80 +80+23 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" {
test unixWm-3.$i {moving window while iconified} unix {
wm iconify .t
sleep 200
@@ -95,7 +110,7 @@ foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
}
set i 1
-foreach geom {+20+80 +100+40 +0+0} {
+foreach geom "+20+80 +100+40 +0+$Y0" {
test unixWm-4.$i {moving window while withdrawn} unix {
wm withdraw .t
sleep 200
@@ -179,27 +194,27 @@ test unixWm-5.7 {compounded state changes} {unix nonPortable} {
destroy .t
toplevel .t -width 200 -height 100
-wm geom .t +10+10
+wm geom .t +10+23
wm minsize .t 1 1
update
test unixWm-6.1 {size changes} unix {
.t config -width 180 -height 150
update
wm geom .t
-} 180x150+10+10
+} 180x150+10+23
test unixWm-6.2 {size changes} unix {
wm geom .t 250x60
.t config -width 170 -height 140
update
wm geom .t
-} 250x60+10+10
+} 250x60+10+23
test unixWm-6.3 {size changes} unix {
wm geom .t 250x60
.t config -width 170 -height 140
wm geom .t {}
update
wm geom .t
-} 170x140+10+10
+} 170x140+10+23
test unixWm-6.4 {size changes} {unix nonPortable userInteraction} {
wm minsize .t 1 1
update
@@ -1357,14 +1372,14 @@ test unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on gr
test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {
destroy .t
toplevel .t
- wm geometry .t 200x100+0+0
+ wm geometry .t 200x100+0+$Y0
listbox .t.l -height 20 -width 20
pack .t.l -fill both -expand 1
update
.t.l configure -setgrid 1
update
wm geometry .t
-} {20x20+0+0}
+} "20x20+0+$Y0"
test unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {
destroy .t
@@ -1559,10 +1574,10 @@ test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
tkwait visibility .t
wm overrideredirect .t 1
update
- wm geometry .t -30+2
+ wm geometry .t -30+$Y2
update
list [winfo x .t] [winfo y .t]
-} [list [expr [winfo screenwidth .t] - 110] 2]
+} [list [expr [winfo screenwidth .t] - 110] $Y2]
destroy .t
test unixWm-44.9 {UpdateGeometryInfo procedure, updating fixed dimensions} {unix testwrapper} {
diff --git a/tests/wm.test b/tests/wm.test
index 7b81985..c2bc385 100644
--- a/tests/wm.test
+++ b/tests/wm.test
@@ -1640,14 +1640,24 @@ test wm-transient-1.7 {usage} -returnCodes error -body {
wm transient .master .master
} -cleanup {
deleteWindows
-} -result {can't make ".master" its own master}
+} -result {setting ".master" as master creates a transient/master cycle}
test wm-transient-1.8 {usage} -returnCodes error -body {
+ toplevel .t1
+ toplevel .t2
+ toplevel .t3
+ wm transient .t2 .t1
+ wm transient .t3 .t2
+ wm transient .t1 .t3
+} -cleanup {
+ deleteWindows
+} -result {setting ".t3" as master creates a transient/master cycle}
+test wm-transient-1.9 {usage} -returnCodes error -body {
toplevel .master
frame .master.f
wm transient .master .master.f
} -cleanup {
deleteWindows
-} -result {can't make ".master" its own master}
+} -result {setting ".master" as master creates a transient/master cycle}
test wm-transient-2.1 {basic get/set of master} -setup {
set results [list]
diff --git a/unix/tkUnixEmbed.c b/unix/tkUnixEmbed.c
index b170ad0..d9203ca 100644
--- a/unix/tkUnixEmbed.c
+++ b/unix/tkUnixEmbed.c
@@ -503,7 +503,15 @@ EmbedStructureProc(
Tk_ErrorHandler errHandler;
if (eventPtr->type == ConfigureNotify) {
+ /*
+ * Send a ConfigureNotify to the embedded application.
+ */
+
+ if (containerPtr->embeddedPtr != None) {
+ TkDoConfigureNotify(containerPtr->embeddedPtr);
+ }
if (containerPtr->wrapper != None) {
+
/*
* Ignore errors, since the embedded application could have
* deleted its window.
@@ -873,6 +881,7 @@ TkpTestembedCmd(
Container *containerPtr;
Tcl_DString dString;
char buffer[50];
+ Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
ThreadSpecificData *tsdPtr =
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
@@ -884,30 +893,45 @@ TkpTestembedCmd(
Tcl_DStringInit(&dString);
for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
containerPtr = containerPtr->nextPtr) {
+ if (containerPtr->embeddedPtr != NULL) {
+ embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
+ }
+ if (containerPtr->parentPtr != NULL) {
+ parentInterp = containerPtr->parentPtr->mainPtr->interp;
+ }
+ if (embeddedInterp != interp && parentInterp != interp) {
+ continue;
+ }
Tcl_DStringStartSublist(&dString);
+ /* Parent id */
if (containerPtr->parent == None) {
Tcl_DStringAppendElement(&dString, "");
} else if (all) {
- sprintf(buffer, "0x%x", (int) containerPtr->parent);
+ sprintf(buffer, "0x%lx", containerPtr->parent);
Tcl_DStringAppendElement(&dString, buffer);
} else {
Tcl_DStringAppendElement(&dString, "XXX");
}
- if (containerPtr->parentPtr == NULL) {
+ /* Parent pathName */
+ if (containerPtr->parentPtr == NULL ||
+ parentInterp != interp) {
Tcl_DStringAppendElement(&dString, "");
} else {
Tcl_DStringAppendElement(&dString,
containerPtr->parentPtr->pathName);
}
+ /* Wrapper */
if (containerPtr->wrapper == None) {
Tcl_DStringAppendElement(&dString, "");
} else if (all) {
- sprintf(buffer, "0x%x", (int) containerPtr->wrapper);
+ sprintf(buffer, "0x%lx", containerPtr->wrapper);
Tcl_DStringAppendElement(&dString, buffer);
} else {
Tcl_DStringAppendElement(&dString, "XXX");
}
- if (containerPtr->embeddedPtr == NULL) {
+ /* Embedded window pathName */
+ if (containerPtr->embeddedPtr == NULL ||
+ embeddedInterp != interp) {
Tcl_DStringAppendElement(&dString, "");
} else {
Tcl_DStringAppendElement(&dString,
diff --git a/unix/tkUnixMenu.c b/unix/tkUnixMenu.c
index 38b6c58..909276a 100644
--- a/unix/tkUnixMenu.c
+++ b/unix/tkUnixMenu.c
@@ -857,11 +857,7 @@ DrawMenuUnderline(
if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
int len;
- /*
- * Do the unicode call just to prevent overruns.
- */
-
- Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
+ len = Tcl_GetCharLength(mePtr->labelPtr);
if (mePtr->underline < len) {
int activeBorderWidth, leftEdge;
const char *label, *start, *end;
@@ -889,7 +885,10 @@ DrawMenuUnderline(
*
* TkpPostMenu --
*
- * Posts a menu on the screen
+ * Posts a menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the entry parameter is negative, the upper left corner of the
+ * menu itself is placed at the point.
*
* Results:
* None.
@@ -904,9 +903,104 @@ int
TkpPostMenu(
Tcl_Interp *interp,
TkMenu *menuPtr,
- int x, int y)
+ int x, int y, int index)
{
- return TkPostTearoffMenu(interp, menuPtr, x, y);
+ return TkpPostTearoffMenu(interp, menuPtr, x, y, index);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPostTearoffMenu --
+ *
+ * Posts a tearoff menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the index parameter is negative, the upper left corner of the menu
+ * itself is placed at the point. On unix this is called when posting
+ * any menu. Adjusts the menu's position so that it fits on the screen,
+ * and maps and raises the menu.
+ *
+ * Results:
+ * Returns a standard Tcl Error.
+ *
+ * Side effects:
+ * The menu is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter of the menu */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y, int index) /* The root X,Y coordinates where the
+ * specified entry will be posted */
+{
+ int vRootX, vRootY, vRootWidth, vRootHeight;
+ int result;
+
+ if (index >= menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
+ TkActivateMenuEntry(menuPtr, -1);
+ TkRecomputeMenu(menuPtr);
+ result = TkPostCommand(menuPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Adjust the position of the menu if necessary to keep it visible on the
+ * screen. There are two special tricks to make this work right:
+ *
+ * 1. If a virtual root window manager is being used then the coordinates
+ * are in the virtual root window of menuPtr's parent; since the menu
+ * uses override-redirect mode it will be in the *real* root window for
+ * the screen, so we have to map the coordinates from the virtual root
+ * (if any) to the real root. Can't get the virtual root from the menu
+ * itself (it will never be seen by the wm) so use its parent instead
+ * (it would be better to have an an option that names a window to use
+ * for this...).
+ * 2. The menu may not have been mapped yet, so its current size might be
+ * the default 1x1. To compute how much space it needs, use its
+ * requested size, not its actual size.
+ */
+
+ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
+ &vRootWidth, &vRootHeight);
+ vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
+ if (x > vRootX + vRootWidth) {
+ x = vRootX + vRootWidth;
+ }
+ if (x < vRootX) {
+ x = vRootX;
+ }
+ vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
+ if (y > vRootY + vRootHeight) {
+ y = vRootY + vRootHeight;
+ }
+ if (y < vRootY) {
+ y = vRootY;
+ }
+ Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
+ if (!Tk_IsMapped(menuPtr->tkwin)) {
+ Tk_MapWindow(menuPtr->tkwin);
+ }
+ TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
+ return TCL_OK;
}
/*
@@ -1721,7 +1815,6 @@ TkpComputeStandardMenuGeometry(
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth
+ 2 * activeBorderWidth + borderWidth;
-
windowHeight += borderWidth;
/*
diff --git a/unix/tkUnixScale.c b/unix/tkUnixScale.c
index 8f88018..2009288 100644
--- a/unix/tkUnixScale.c
+++ b/unix/tkUnixScale.c
@@ -150,11 +150,11 @@ DisplayVerticalScale(
for (tickValue = scalePtr->fromValue; ;
tickValue += tickInterval) {
/*
- * The TkRoundToResolution call gets rid of accumulated
+ * The TkRoundValueToResolution call gets rid of accumulated
* round-off errors, if any.
*/
- tickValue = TkRoundToResolution(scalePtr, tickValue);
+ tickValue = TkRoundValueToResolution(scalePtr, tickValue);
if (scalePtr->toValue >= scalePtr->fromValue) {
if (tickValue > scalePtr->toValue) {
break;
@@ -370,11 +370,11 @@ DisplayHorizontalScale(
for (tickValue = scalePtr->fromValue; ;
tickValue += tickInterval) {
/*
- * The TkRoundToResolution call gets rid of accumulated
+ * The TkRoundValueToResolution call gets rid of accumulated
* round-off errors, if any.
*/
- tickValue = TkRoundToResolution(scalePtr, tickValue);
+ tickValue = TkRoundValueToResolution(scalePtr, tickValue);
if (scalePtr->toValue >= scalePtr->fromValue) {
if (tickValue > scalePtr->toValue) {
break;
diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c
index 8944ecc..9ed9082 100644
--- a/unix/tkUnixWm.c
+++ b/unix/tkUnixWm.c
@@ -3524,7 +3524,7 @@ WmTransientCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
- TkWindow *masterPtr = wmPtr->masterPtr;
+ TkWindow *masterPtr = wmPtr->masterPtr, *w;
WmInfo *wmPtr2;
if ((objc != 3) && (objc != 4)) {
@@ -3593,12 +3593,18 @@ WmTransientCmd(
return TCL_ERROR;
}
- if (masterPtr == winPtr) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't make \"%s\" its own master", Tk_PathName(winPtr)));
- Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
- return TCL_ERROR;
- } else if (masterPtr != wmPtr->masterPtr) {
+ for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
+ w = (TkWindow *)w->wmInfoPtr->masterPtr) {
+ if (w == winPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "setting \"%s\" as master creates a transient/master cycle",
+ Tk_PathName(masterPtr)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (masterPtr != wmPtr->masterPtr) {
/*
* Remove old master map/unmap binding before setting the new
* master. The event handler will ensure that transient states
diff --git a/win/makefile.vc b/win/makefile.vc
index 947e167..1e44bff 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -336,6 +336,9 @@ all: release $(CAT32)
core: setup $(TKSTUBLIB) $(TKLIB)
cwish: $(WISHC)
install: install-binaries install-libraries install-docs
+!if $(SYMBOLS)
+install: install-pdbs
+!endif
tktest: setup $(TKTEST) $(CAT32)
setup: default-setup
@@ -516,6 +519,11 @@ install-docs:
!endif
# "emacs font-lock highlighting fix
+install-pdbs:
+ @echo Installing debug symbols
+ @$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
+# "emacs font-lock highlighting fix
+
#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------
diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c
index 877eed4..8c6a4a4 100644
--- a/win/tkWinClipboard.c
+++ b/win/tkWinClipboard.c
@@ -79,9 +79,7 @@ TkSelGetSelection(
goto error;
}
data = GlobalLock(handle);
- Tcl_DStringInit(&ds);
- Tcl_UniCharToUtfDString((Tcl_UniChar *)data,
- Tcl_UniCharLen((Tcl_UniChar *)data), &ds);
+ Tcl_WinTCharToUtf((TCHAR *)data, -1, &ds);
GlobalUnlock(handle);
} else if (IsClipboardFormatAvailable(CF_TEXT)) {
/*
@@ -151,15 +149,15 @@ TkSelGetSelection(
if (drop->fWide) {
WCHAR *fname = (WCHAR *) ((char *) drop + drop->pFiles);
Tcl_DString dsTmp;
- int count = 0, len;
+ int count = 0;
+ size_t len;
while (*fname != 0) {
if (count) {
Tcl_DStringAppend(&ds, "\n", 1);
}
- len = Tcl_UniCharLen((Tcl_UniChar *) fname);
- Tcl_DStringInit(&dsTmp);
- Tcl_UniCharToUtfDString((Tcl_UniChar *) fname, len, &dsTmp);
+ len = wcslen(fname);
+ Tcl_WinTCharToUtf(fname, len * sizeof(WCHAR), &dsTmp);
Tcl_DStringAppend(&ds, Tcl_DStringValue(&dsTmp),
Tcl_DStringLength(&dsTmp));
Tcl_DStringFree(&dsTmp);
diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c
index 366485b..4ad3b9e 100644
--- a/win/tkWinDialog.c
+++ b/win/tkWinDialog.c
@@ -2911,13 +2911,10 @@ Tk_MessageBoxObjCmd(
flags |= icon | type | MB_TASKMODAL | MB_SETFOREGROUND;
- tmpObj = messageObj ? Tcl_DuplicateObj(messageObj)
- : Tcl_NewUnicodeObj(NULL, 0);
+ tmpObj = messageObj ? Tcl_DuplicateObj(messageObj) : Tcl_NewObj();
Tcl_IncrRefCount(tmpObj);
if (detailObj) {
- const Tcl_UniChar twoNL[] = { '\n', '\n' };
-
- Tcl_AppendUnicodeToObj(tmpObj, twoNL, 2);
+ Tcl_AppendStringsToObj(tmpObj, "\n\n", NULL);
Tcl_AppendObjToObj(tmpObj, detailObj);
}
diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c
index 43c5e25..6c80964 100644
--- a/win/tkWinEmbed.c
+++ b/win/tkWinEmbed.c
@@ -856,6 +856,15 @@ ContainerEventProc(
Tk_Window tkwin = (Tk_Window)containerPtr->parentPtr;
if (eventPtr->type == ConfigureNotify) {
+
+ /*
+ * Send a ConfigureNotify to the embedded application.
+ */
+
+ if (containerPtr->embeddedPtr != NULL) {
+ TkDoConfigureNotify(containerPtr->embeddedPtr);
+ }
+
/*
* Resize the embedded window, if there is any.
*/
diff --git a/win/tkWinInit.c b/win/tkWinInit.c
index 4c18399..780888a 100644
--- a/win/tkWinInit.c
+++ b/win/tkWinInit.c
@@ -199,7 +199,7 @@ TkWin32ErrorObj(
}
#ifdef _UNICODE
- Tcl_WinTCharToUtf(lpBuffer, (int)wcslen(lpBuffer) * sizeof (WCHAR), &ds);
+ Tcl_WinTCharToUtf(lpBuffer, wcslen(lpBuffer) * sizeof (WCHAR), &ds);
errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
Tcl_DStringFree(&ds);
#else
diff --git a/win/tkWinKey.c b/win/tkWinKey.c
index 357a804..8db34af 100644
--- a/win/tkWinKey.c
+++ b/win/tkWinKey.c
@@ -122,7 +122,7 @@ TkpGetString(
if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
|| (keysym == XK_Return) || (keysym == XK_Tab)) {
- len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
+ len = Tcl_UniCharToUtf(keysym & 255, buf);
Tcl_DStringAppend(dsPtr, buf, len);
}
}
diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c
index dd7d1cb..3223759 100644
--- a/win/tkWinMenu.c
+++ b/win/tkWinMenu.c
@@ -743,7 +743,10 @@ ReconfigureWindowsMenu(
*
* TkpPostMenu --
*
- * Posts a menu on the screen
+ * Posts a menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the entry parameter is negative, the upper left corner of the
+ * menu itself is placed at the point.
*
* Results:
* None.
@@ -758,7 +761,7 @@ int
TkpPostMenu(
Tcl_Interp *interp,
TkMenu *menuPtr,
- int x, int y)
+ int x, int y, int index)
{
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
int result, flags;
@@ -770,7 +773,6 @@ TkpPostMenu(
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
tsdPtr->inPostMenu++;
-
CallPendingReconfigureImmediately(menuPtr);
result = TkPreprocessMenu(menuPtr);
@@ -779,6 +781,13 @@ TkpPostMenu(
return result;
}
+ if (index >= menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
/*
* The post commands could have deleted the menu, which means
* we are dead and should go away.
@@ -841,6 +850,100 @@ TkpPostMenu(
/*
*----------------------------------------------------------------------
*
+ * TkpPostTearoffMenu --
+ *
+ * Posts a tearoff menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the index parameter is negative, the upper left corner of the menu
+ * itself is placed at the point. Adjusts the menu's position so that it
+ * fits on the screen, and maps and raises the menu.
+ *
+ * Results:
+ * Returns a standard Tcl Error.
+ *
+ * Side effects:
+ * The menu is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter of the menu */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y, int index) /* The root X,Y coordinates where we are
+ * posting */
+{
+ int vRootX, vRootY, vRootWidth, vRootHeight;
+ int result;
+
+ if (index >= menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
+ TkActivateMenuEntry(menuPtr, -1);
+ TkRecomputeMenu(menuPtr);
+ result = TkPostCommand(menuPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Adjust the position of the menu if necessary to keep it visible on the
+ * screen. There are two special tricks to make this work right:
+ *
+ * 1. If a virtual root window manager is being used then the coordinates
+ * are in the virtual root window of menuPtr's parent; since the menu
+ * uses override-redirect mode it will be in the *real* root window for
+ * the screen, so we have to map the coordinates from the virtual root
+ * (if any) to the real root. Can't get the virtual root from the menu
+ * itself (it will never be seen by the wm) so use its parent instead
+ * (it would be better to have an an option that names a window to use
+ * for this...).
+ * 2. The menu may not have been mapped yet, so its current size might be
+ * the default 1x1. To compute how much space it needs, use its
+ * requested size, not its actual size.
+ */
+
+ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
+ &vRootWidth, &vRootHeight);
+ vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
+ if (x > vRootX + vRootWidth) {
+ x = vRootX + vRootWidth;
+ }
+ if (x < vRootX) {
+ x = vRootX;
+ }
+ vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
+ if (y > vRootY + vRootHeight) {
+ y = vRootY + vRootHeight;
+ }
+ if (y < vRootY) {
+ y = vRootY;
+ }
+ Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
+ if (!Tk_IsMapped(menuPtr->tkwin)) {
+ Tk_MapWindow(menuPtr->tkwin);
+ }
+ TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpMenuNewEntry --
*
* Adds a pointer to a new menu entry structure with the platform-
@@ -1146,7 +1249,9 @@ TkWinHandleMenuEvent(
if (hashEntryPtr != NULL) {
int i, len, underline;
Tcl_Obj *labelPtr;
- Tcl_UniChar *wlabel, menuChar;
+ WCHAR *wlabel;
+ int menuChar;
+ Tcl_DString ds;
*plResult = 0;
menuPtr = Tcl_GetHashValue(hashEntryPtr);
@@ -1154,8 +1259,9 @@ TkWinHandleMenuEvent(
* Assume we have something directly convertable to Tcl_UniChar.
* True at least for wide systems.
*/
- menuChar = Tcl_UniCharToUpper((Tcl_UniChar) LOWORD(*pwParam));
+ menuChar = Tcl_UniCharToUpper(LOWORD(*pwParam));
+ Tcl_DStringInit(&ds);
for (i = 0; i < menuPtr->numEntries; i++) {
underline = menuPtr->entries[i]->underline;
labelPtr = menuPtr->entries[i]->labelPtr;
@@ -1163,7 +1269,10 @@ TkWinHandleMenuEvent(
/*
* Ensure we don't exceed the label length, then check
*/
- wlabel = Tcl_GetUnicodeFromObj(labelPtr, &len);
+ const char *src = Tcl_GetStringFromObj(labelPtr, &len);
+
+ Tcl_DStringFree(&ds);
+ wlabel = (WCHAR *) Tcl_WinUtfToTChar(src, len, &ds);
if ((underline < len) && (menuChar ==
Tcl_UniCharToUpper(wlabel[underline]))) {
*plResult = (2 << 16) | i;
@@ -1172,6 +1281,7 @@ TkWinHandleMenuEvent(
}
}
}
+ Tcl_DStringFree(&ds);
}
break;
}
@@ -1967,8 +2077,7 @@ DrawMenuUnderline(
if ((mePtr->underline >= 0) && (mePtr->labelPtr != NULL)) {
int len;
- /* do the unicode call just to prevent overruns */
- Tcl_GetUnicodeFromObj(mePtr->labelPtr, &len);
+ len = Tcl_GetCharLength(mePtr->labelPtr);
if (mePtr->underline < len) {
const char *label, *start, *end;
@@ -2364,7 +2473,7 @@ DrawMenuEntryLabel(
XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y,
(unsigned) width, (unsigned) height);
} else if ((mePtr->image != NULL)
- && (menuPtr->disabledImageGC != NULL)) {
+ && menuPtr->disabledImageGC) {
XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC,
leftEdge + imageXOffset,
(int) (y + (mePtr->height - imageHeight)/2 + imageYOffset),
@@ -2897,7 +3006,6 @@ TkpComputeStandardMenuGeometry(
GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,
fmPtr, &width, &height);
menuPtr->entries[i]->height = height;
-
} else {
/*
* For each entry, compute the height required by that particular
@@ -2955,8 +3063,6 @@ TkpComputeStandardMenuGeometry(
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth
+ 2 * activeBorderWidth + borderWidth;
-
-
windowHeight += borderWidth;
/*
diff --git a/win/tkWinWm.c b/win/tkWinWm.c
index 97cf255..5bb23d1 100644
--- a/win/tkWinWm.c
+++ b/win/tkWinWm.c
@@ -5526,7 +5526,7 @@ WmTransientCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
- TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr;
+ TkWindow *masterPtr = wmPtr->masterPtr, **masterPtrPtr = &masterPtr, *w;
WmInfo *wmPtr2;
if ((objc != 3) && (objc != 4)) {
@@ -5584,13 +5584,17 @@ WmTransientCmd(
Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
return TCL_ERROR;
}
-
- if (masterPtr == winPtr) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't make \"%s\" its own master", Tk_PathName(winPtr)));
- Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
- return TCL_ERROR;
- } else if (masterPtr != wmPtr->masterPtr) {
+ for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
+ w = (TkWindow *)w->wmInfoPtr->masterPtr) {
+ if (w == winPtr) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "setting \"%s\" as master creates a transient/master cycle",
+ Tk_PathName(masterPtr)));
+ Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (masterPtr != wmPtr->masterPtr) {
/*
* Remove old master map/unmap binding before setting the new
* master. The event handler will ensure that transient states
diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c
index 3de1504..b828221 100644
--- a/win/ttkWinXPTheme.c
+++ b/win/ttkWinXPTheme.c
@@ -455,7 +455,7 @@ InitElementData(ElementData *elementData, Tk_Window tkwin, Drawable d)
{
Window win = Tk_WindowId(tkwin);
- if (win != None) {
+ if (win) {
elementData->hwnd = Tk_GetHWND(win);
} else {
elementData->hwnd = elementData->procs->stubWindow;
@@ -829,16 +829,21 @@ static void TextElementSize(
ElementData *elementData = clientData;
RECT rc = {0, 0};
HRESULT hr = S_OK;
+ const char *src;
+ int len;
+ Tcl_DString ds;
if (!InitElementData(elementData, tkwin, 0))
return;
+ src = Tcl_GetStringFromObj(element->textObj, &len);
+ Tcl_WinUtfToTChar(src, len, &ds);
hr = elementData->procs->GetThemeTextExtent(
elementData->hTheme,
elementData->hDC,
elementData->info->partId,
Ttk_StateTableLookup(elementData->info->statemap, 0),
- Tcl_GetUnicode(element->textObj),
+ (WCHAR *) Tcl_DStringValue(&ds),
-1,
DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
NULL,
@@ -851,6 +856,7 @@ static void TextElementSize(
if (*widthPtr < 80) *widthPtr = 80;
if (*heightPtr < 20) *heightPtr = 20;
+ Tcl_DStringFree(&ds);
FreeElementData(elementData);
}
@@ -862,20 +868,27 @@ static void TextElementDraw(
ElementData *elementData = clientData;
RECT rc = BoxToRect(b);
HRESULT hr = S_OK;
+ const char *src;
+ int len;
+ Tcl_DString ds;
if (!InitElementData(elementData, tkwin, d))
return;
+ src = Tcl_GetStringFromObj(element->textObj, &len);
+ Tcl_WinUtfToTChar(src, len, &ds);
hr = elementData->procs->DrawThemeText(
elementData->hTheme,
elementData->hDC,
elementData->info->partId,
Ttk_StateTableLookup(elementData->info->statemap, state),
- Tcl_GetUnicode(element->textObj),
+ (WCHAR *) Tcl_DStringValue(&ds),
-1,
DT_LEFT,// | DT_BOTTOM | DT_NOPREFIX,
(state & TTK_STATE_DISABLED) ? DTT_GRAYED : 0,
&rc);
+
+ Tcl_DStringFree(&ds);
FreeElementData(elementData);
}
@@ -1102,7 +1115,7 @@ Ttk_CreateVsapiElement(
XPThemeData *themeData = clientData;
ElementInfo *elementPtr = NULL;
ClientData elementData;
- Tcl_UniChar *className;
+ WCHAR *className;
int partId = 0;
Ttk_StateTable *stateTable;
Ttk_Padding pad = {0, 0, 0, 0};
@@ -1111,6 +1124,7 @@ Ttk_CreateVsapiElement(
char *name;
LPWSTR wname;
Ttk_ElementSpec *elementSpec = &GenericElementSpec;
+ Tcl_DString classBuf;
static const char *optionStrings[] =
{ "-padding","-width","-height","-margins", "-syssize",
@@ -1128,7 +1142,8 @@ Ttk_CreateVsapiElement(
if (Tcl_GetIntFromObj(interp, objv[1], &partId) != TCL_OK) {
return TCL_ERROR;
}
- className = Tcl_GetUnicodeFromObj(objv[0], &length);
+ name = Tcl_GetStringFromObj(objv[0], &length);
+ className = (WCHAR *) Tcl_WinUtfToTChar(name, length, &classBuf);
/* flags or padding */
if (objc > 3) {
@@ -1140,54 +1155,54 @@ Ttk_CreateVsapiElement(
"Missing value for \"%s\".",
Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TTK", "VSAPI", "MISSING", NULL);
- return TCL_ERROR;
+ goto retErr;
}
if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings,
sizeof(char *), "option", 0, &option) != TCL_OK)
- return TCL_ERROR;
+ goto retErr;
switch (option) {
case O_PADDING:
if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
break;
case O_MARGINS:
if (Ttk_GetBorderFromObj(interp, objv[i+1], &pad) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
flags |= PAD_MARGINS;
break;
case O_WIDTH:
if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
pad.left = pad.right = tmp;
flags |= IGNORE_THEMESIZE;
break;
case O_HEIGHT:
if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
pad.top = pad.bottom = tmp;
flags |= IGNORE_THEMESIZE;
break;
case O_SYSSIZE:
if (GetSysFlagFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
elementSpec = &GenericSizedElementSpec;
flags |= (tmp & 0xFFFF);
break;
case O_HALFHEIGHT:
if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
if (tmp)
flags |= HALF_HEIGHT;
break;
case O_HALFWIDTH:
if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
- return TCL_ERROR;
+ goto retErr;
}
if (tmp)
flags |= HALF_WIDTH;
@@ -1201,7 +1216,7 @@ Ttk_CreateVsapiElement(
Tcl_Obj **specs;
int n,j,count, status = TCL_OK;
if (Tcl_ListObjGetElements(interp, objv[2], &count, &specs) != TCL_OK)
- return TCL_ERROR;
+ goto retErr;
/* we over-allocate to ensure there is a terminating entry */
stateTable = ckalloc(sizeof(Ttk_StateTable) * (count + 1));
memset(stateTable, 0, sizeof(Ttk_StateTable) * (count + 1));
@@ -1217,6 +1232,7 @@ Ttk_CreateVsapiElement(
}
if (status != TCL_OK) {
ckfree(stateTable);
+ Tcl_DStringFree(&classBuf);
return status;
}
} else {
@@ -1237,7 +1253,7 @@ Ttk_CreateVsapiElement(
elementPtr->elementName = name;
/* set the class name to an allocated copy */
- wname = ckalloc(sizeof(WCHAR) * (length + 1));
+ wname = ckalloc(Tcl_DStringLength(&classBuf) + sizeof(WCHAR));
wcscpy(wname, className);
elementPtr->className = wname;
@@ -1247,7 +1263,12 @@ Ttk_CreateVsapiElement(
Ttk_RegisterCleanup(interp, elementData, DestroyElementData);
Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1));
+ Tcl_DStringFree(&classBuf);
return TCL_OK;
+
+retErr:
+ Tcl_DStringFree(&classBuf);
+ return TCL_ERROR;
}
/*----------------------------------------------------------------------