Tk Source Code

Check-in [d0256ba4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | revised_text | tip-466
Files: files | file ages | folders
SHA3-256: d0256ba4d7fcbb450d7bafcdb1e2cb4c1ca3a7f409da744be2f83d14a4f24ef8
User & Date: fvogel 2019-02-22 19:00:29.529
Context
2019-03-14
21:05
merge trunk check-in: 76d45a3e user: fvogel tags: revised_text, tip-466
2019-02-22
19:00
merge trunk check-in: d0256ba4 user: fvogel tags: revised_text, tip-466
18:50
Fix [30a0fc767a]: spelling error in a comment check-in: dcf35904 user: fvogel tags: trunk
2019-01-20
21:13
Merge trunk check-in: 98229b58 user: jan.nijtmans tags: revised_text, tip-466
Changes
Unified Diff Ignore Whitespace Patch
Changes to doc/menu.n.
466
467
468
469
470
471
472
473
474
475
476


477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
entry has a command associated with it then the result of that
command is returned as the result of the \fBinvoke\fR widget
command.  Otherwise the result is an empty string.  Note:  invoking
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
.
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.
.TP
\fIpathName \fBpostcascade \fIindex\fR
.
Posts the submenu associated with the cascade entry given by
\fIindex\fR, and unposts any previously posted submenu.
If \fIindex\fR does not correspond to a cascade entry,
or if \fIpathName\fR is not posted,







|


|
>
>
|
|
|
|
|
<
|
|







466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
entry has a command associated with it then the result of that
command is returned as the result of the \fBinvoke\fR widget
command.  Otherwise the result is an empty string.  Note:  invoking
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 ?\fIindex\fR?
.
Arrange for the menu to be displayed on the screen at the root-window
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
.
Posts the submenu associated with the cascade entry given by
\fIindex\fR, and unposts any previously posted submenu.
If \fIindex\fR does not correspond to a cascade entry,
or if \fIpathName\fR is not posted,
Changes to generic/tk.h.
583
584
585
586
587
588
589



590

591
592
593
594
595
596
597

typedef Window (Tk_ClassCreateProc) (Tk_Window tkwin, Window parent,
	ClientData instanceData);
typedef void (Tk_ClassWorldChangedProc) (ClientData instanceData);
typedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr);

typedef struct Tk_ClassProcs {



    unsigned int size;

    Tk_ClassWorldChangedProc *worldChangedProc;
				/* Procedure to invoke when the widget needs
				 * to respond in some way to a change in the
				 * world (font changes, etc.) */
    Tk_ClassCreateProc *createProc;
				/* Procedure to invoke when the platform-
				 * dependent window needs to be created. */







>
>
>

>







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601

typedef Window (Tk_ClassCreateProc) (Tk_Window tkwin, Window parent,
	ClientData instanceData);
typedef void (Tk_ClassWorldChangedProc) (ClientData instanceData);
typedef void (Tk_ClassModalProc) (Tk_Window tkwin, XEvent *eventPtr);

typedef struct Tk_ClassProcs {
#if TCL_MAJOR_VERSION > 8
    size_t size;
#else
    unsigned int size;
#endif
    Tk_ClassWorldChangedProc *worldChangedProc;
				/* Procedure to invoke when the widget needs
				 * to respond in some way to a change in the
				 * world (font changes, etc.) */
    Tk_ClassCreateProc *createProc;
				/* Procedure to invoke when the platform-
				 * dependent window needs to be created. */
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
 *	#define Tk_GetField(name, who, which) \
 *	    (((who) == NULL) ? NULL :
 *	    (((who)->size <= Tk_Offset(name, which)) ? NULL :(name)->which))
 */

#define Tk_GetClassProc(procs, which) \
    (((procs) == NULL) ? NULL : \
    (((procs)->size <= Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which))

/*
 * Each geometry manager (the packer, the placer, etc.) is represented by a
 * structure of the following form, which indicates procedures to invoke in
 * the geometry manager to carry out certain functions.
 */








|







617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
 *	#define Tk_GetField(name, who, which) \
 *	    (((who) == NULL) ? NULL :
 *	    (((who)->size <= Tk_Offset(name, which)) ? NULL :(name)->which))
 */

#define Tk_GetClassProc(procs, which) \
    (((procs) == NULL) ? NULL : \
    (((procs)->size <= (size_t)Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which))

/*
 * Each geometry manager (the packer, the placer, etc.) is represented by a
 * structure of the following form, which indicates procedures to invoke in
 * the geometry manager to carry out certain functions.
 */

1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
 * The definitions below provide backward compatibility for functions and
 * types related to event handling that used to be in Tk but have moved to
 * Tcl.
 *
 *----------------------------------------------------------------------
 */


#define TK_READABLE		TCL_READABLE
#define TK_WRITABLE		TCL_WRITABLE
#define TK_EXCEPTION		TCL_EXCEPTION

#define TK_DONT_WAIT		TCL_DONT_WAIT
#define TK_X_EVENTS		TCL_WINDOW_EVENTS
#define TK_WINDOW_EVENTS	TCL_WINDOW_EVENTS







>







1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
 * The definitions below provide backward compatibility for functions and
 * types related to event handling that used to be in Tk but have moved to
 * Tcl.
 *
 *----------------------------------------------------------------------
 */

#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
#define TK_READABLE		TCL_READABLE
#define TK_WRITABLE		TCL_WRITABLE
#define TK_EXCEPTION		TCL_EXCEPTION

#define TK_DONT_WAIT		TCL_DONT_WAIT
#define TK_X_EVENTS		TCL_WINDOW_EVENTS
#define TK_WINDOW_EVENTS	TCL_WINDOW_EVENTS
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520
1521
1522
1523

/* Additional stuff that has moved to Tcl: */

#define Tk_EventuallyFree	Tcl_EventuallyFree
#define Tk_FreeProc		Tcl_FreeProc
#define Tk_Preserve		Tcl_Preserve
#define Tk_Release		Tcl_Release


/* Removed Tk_Main, use macro instead */
#if defined(_WIN32) || defined(__CYGWIN__)
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
	(Tcl_FindExecutable(0), (Tcl_CreateInterp)()))
#else
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \







>







1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

/* Additional stuff that has moved to Tcl: */

#define Tk_EventuallyFree	Tcl_EventuallyFree
#define Tk_FreeProc		Tcl_FreeProc
#define Tk_Preserve		Tcl_Preserve
#define Tk_Release		Tcl_Release
#endif

/* Removed Tk_Main, use macro instead */
#if defined(_WIN32) || defined(__CYGWIN__)
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
	(Tcl_FindExecutable(0), (Tcl_CreateInterp)()))
#else
#define Tk_Main(argc, argv, proc) Tk_MainEx(argc, argv, proc, \
Changes to generic/tkFocus.c.
547
548
549
550
551
552
553





554
555
556

557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
     * Don't set focus if window is already dead. [Bug 3574708]
     */

    if (winPtr->flags & TK_ALREADY_DEAD) {
	return;
    }






    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.
     */

    if (winPtr == displayFocusPtr->focusWinPtr && !force) {
	return;
    }

    /*
     * 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
     * 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.
	     */

	    return;
	}
	if (!(topLevelPtr->flags & TK_MAPPED)) {
	    allMapped = 0;
	}
	if (topLevelPtr->flags & TK_TOP_HIERARCHY) {
	    break;
	}
    }

    /*
     * 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 (displayFocusPtr->focusOnMapPtr != NULL) {
	Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr,
		StructureNotifyMask, FocusMapProc,
		displayFocusPtr->focusOnMapPtr);
	displayFocusPtr->focusOnMapPtr = NULL;







>
>
>
>
>



>
|
<
|







|
|






>
















|
|
|
|
|







547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
     * Don't set focus if window is already dead. [Bug 3574708]
     */

    if (winPtr->flags & TK_ALREADY_DEAD) {
	return;
    }

    /*
     * Get the current focus window with the same display and application
     * as winPtr.
     */

    displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);

    /*
     * 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) {
	return;
    }

    /*
     * 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.
	     */

	    return;
	}
	if (!(topLevelPtr->flags & TK_MAPPED)) {
	    allMapped = 0;
	}
	if (topLevelPtr->flags & TK_TOP_HIERARCHY) {
	    break;
	}
    }

    /*
     * 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) {
	Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr,
		StructureNotifyMask, FocusMapProc,
		displayFocusPtr->focusOnMapPtr);
	displayFocusPtr->focusOnMapPtr = NULL;
619
620
621
622
623
624
625


626
627

628


629
630


631

632
633
634
635
636
637
638


639

640


641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
	tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr->topLevelPtr = topLevelPtr;
	tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
	winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
    }
    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)


	    && (displayFocusPtr->focusWinPtr == NULL)) {

	TkpClaimFocus(topLevelPtr, force);


    } else if ((displayFocusPtr->focusWinPtr != NULL) || force) {
	/*
	 * 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.
	 */

	serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);
	if (serial != 0) {
	    displayFocusPtr->focusSerial = serial;
	}
	GenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr);
	displayFocusPtr->focusWinPtr = winPtr;
	winPtr->dispPtr->focusPtr = winPtr;







>
>
|
<
>
|
>
>
|
|
>
>
|
>
|
|
<
|
|
|
|
>
>
|
>
|
>
>
|

<
|
|
<
<

|







625
626
627
628
629
630
631
632
633
634

635
636
637
638
639
640
641
642
643
644
645
646

647
648
649
650
651
652
653
654
655
656
657
658
659

660
661


662
663
664
665
666
667
668
669
670
	tlFocusPtr = ckalloc(sizeof(ToplevelFocusInfo));
	tlFocusPtr->topLevelPtr = topLevelPtr;
	tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr;
	winPtr->mainPtr->tlFocusPtr = tlFocusPtr;
    }
    tlFocusPtr->focusWinPtr = winPtr;

    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.
	 */

	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;
	    }
    	}

	/*

	 * Call the platform specific function TkpChangeFocus to move the
	 * window manager's focus to a new toplevel.


	 */
	
	serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force);
	if (serial != 0) {
	    displayFocusPtr->focusSerial = serial;
	}
	GenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr);
	displayFocusPtr->focusWinPtr = winPtr;
	winPtr->dispPtr->focusPtr = winPtr;
Changes to generic/tkMenu.c.
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885



886


887

888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
	if (index < 0) {
	    goto done;
	}
	result = TkInvokeMenu(interp, menuPtr, index);
	break;
    }
    case MENU_POST: {
	int x, y;

	if (objc != 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    goto error;
	}
	if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
		|| (Tcl_GetIntFromObj(interp, objv[3], &y) != 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).
	 */

	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);
	} else {
	    result = TkPostTearoffMenu(interp, menuPtr, x, y);
	}
	break;
    }
    case MENU_POSTCASCADE: {
	int index;

	if (objc != 3) {







|

|
|






>
>
>
|
>
>

>
|
|
|
|
<






|

|







869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
	if (index < 0) {
	    goto done;
	}
	result = TkInvokeMenu(interp, menuPtr, index);
	break;
    }
    case MENU_POST: {
	int x, y, index = -1;

	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 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, index);
	} else {
	    result = TkpPostTearoffMenu(interp, menuPtr, x, y, index);
	}
	break;
    }
    case MENU_POSTCASCADE: {
	int index;

	if (objc != 3) {
Changes to generic/tkMenu.h.
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
			    int imgHeight);
MODULE_SCOPE Tcl_Obj *	TkNewMenuName(Tcl_Interp *interp,
			    Tcl_Obj *parentNamePtr, TkMenu *menuPtr);
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);
MODULE_SCOPE int	TkPreprocessMenu(TkMenu *menuPtr);
MODULE_SCOPE void	TkRecomputeMenu(TkMenu *menuPtr);

/*
 * These routines are the platform-dependent routines called by the common
 * code.
 */







|







517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
			    int imgHeight);
MODULE_SCOPE Tcl_Obj *	TkNewMenuName(Tcl_Interp *interp,
			    Tcl_Obj *parentNamePtr, TkMenu *menuPtr);
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);
MODULE_SCOPE int	TkPreprocessMenu(TkMenu *menuPtr);
MODULE_SCOPE void	TkRecomputeMenu(TkMenu *menuPtr);

/*
 * These routines are the platform-dependent routines called by the common
 * code.
 */
540
541
542
543
544
545
546
547


548
549
550
			    const Tk_FontMetrics *menuMetricsPtr, int x,
			    int y, int width, int height, int strictMotif,
			    int drawingParameters);
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);


MODULE_SCOPE void	TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr);

#endif /* _TKMENU */







|
>
>



540
541
542
543
544
545
546
547
548
549
550
551
552
			    const Tk_FontMetrics *menuMetricsPtr, int x,
			    int y, int width, int height, int strictMotif,
			    int drawingParameters);
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 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 */
Changes to generic/tkMenuDraw.c.
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	Returns a standard Tcl Error.
 *
 * Side effects:
 *	The menu is posted.
 *
 *----------------------------------------------------------------------
 */

int
TkPostTearoffMenu(
    Tcl_Interp *interp,		/* The interpreter of the menu */
    TkMenu *menuPtr,		/* The menu we are posting */
    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;
}

/*
 *--------------------------------------------------------------
 *
 * TkPostSubmenu --
 *







<
|
|

















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
















829









































830
831
832
833
834
835
836
}

/*
 *----------------------------------------------------------------------
 *
 * TkPostTearoffMenu --
 *

 *	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.
 *
 * Side effects:
 *	The menu is posted.
 *
 *----------------------------------------------------------------------
 */

int
TkPostTearoffMenu(
    Tcl_Interp *interp,		/* The interpreter of the menu */
    TkMenu *menuPtr,		/* The menu we are posting */
    int x, int y)		/* The root X,Y coordinates where we are
				 * posting */
{
















    return TkpPostTearoffMenu(interp, menuPtr, x, y, -1);









































}

/*
 *--------------------------------------------------------------
 *
 * TkPostSubmenu --
 *
Changes to generic/tkPlace.c.
1181
1182
1183
1184
1185
1186
1187






1188
1189
1190
1191
1192
1193
1194
    Tk_Window tkwin)		/* Window that changed its desired size. */
{
    Slave *slavePtr = clientData;
    Master *masterPtr;

    if ((slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH))
	    && (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT))) {






	return;
    }
    masterPtr = slavePtr->masterPtr;
    if (masterPtr == NULL) {
	return;
    }
    if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {







>
>
>
>
>
>







1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
    Tk_Window tkwin)		/* Window that changed its desired size. */
{
    Slave *slavePtr = clientData;
    Master *masterPtr;

    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;
    if (masterPtr == NULL) {
	return;
    }
    if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
Changes to generic/tkScale.c.
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
	    double value;
	    Tcl_Obj *valuePtr;

	    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
		    TCL_GLOBAL_ONLY);
	    if ((valuePtr != NULL) &&
		    (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
		scalePtr->value = TkRoundToResolution(scalePtr, value);
	    }
	}

	/*
	 * Several options need special processing, such as parsing the
	 * orientation and creating GCs.
	 */

	scalePtr->fromValue = TkRoundToResolution(scalePtr,
		scalePtr->fromValue);
	scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
	scalePtr->tickInterval = TkRoundToResolution(scalePtr,
		scalePtr->tickInterval);

	/*
	 * Make sure that the tick interval has the right sign so that
	 * addition moves from fromValue to toValue.
	 */








|








|

|
|







607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
	    double value;
	    Tcl_Obj *valuePtr;

	    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
		    TCL_GLOBAL_ONLY);
	    if ((valuePtr != NULL) &&
		    (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
		scalePtr->value = TkRoundValueToResolution(scalePtr, value);
	    }
	}

	/*
	 * Several options need special processing, such as parsing the
	 * orientation and creating GCs.
	 */

	scalePtr->fromValue = TkRoundValueToResolution(scalePtr,
		scalePtr->fromValue);
	scalePtr->toValue = TkRoundValueToResolution(scalePtr, scalePtr->toValue);
	scalePtr->tickInterval = TkRoundIntervalToResolution(scalePtr,
		scalePtr->tickInterval);

	/*
	 * Make sure that the tick interval has the right sign so that
	 * addition moves from fromValue to toValue.
	 */

1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125




1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137









1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
    }
    scalePtr->flags |= what;
}

/*
 *--------------------------------------------------------------
 *
 * TkRoundToResolution --
 *
 *	Round a given floating-point value to the nearest multiple of the
 *	scale's resolution.




 *
 * Results:
 *	The return value is the rounded result.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

double
TkRoundToResolution(









    TkScale *scalePtr,		/* Information about scale widget. */
    double value)		/* Value to round. */
{
    double rem, rounded, tick;

    if (scalePtr->resolution <= 0) {
	return value;
    }
    tick = floor(value/scalePtr->resolution);
    rounded = scalePtr->resolution * tick;
    rem = value - rounded;
    if (rem < 0) {
	if (rem <= -scalePtr->resolution/2) {
	    rounded = (tick - 1.0) * scalePtr->resolution;
	}
    } else {
	if (rem >= scalePtr->resolution/2) {
	    rounded = (tick + 1.0) * scalePtr->resolution;
	}
    }
    return rounded;
}

/*
 *----------------------------------------------------------------------
 *







|



>
>
>
>











|
>
>
>
>
>
>
>
>
>












|
|
|

|
|
|







1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
    }
    scalePtr->flags |= what;
}

/*
 *--------------------------------------------------------------
 *
 * 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.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */

double
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. */
{
    double rem, rounded, tick;

    if (scalePtr->resolution <= 0) {
	return value;
    }
    tick = floor(value/scalePtr->resolution);
    rounded = scalePtr->resolution * tick;
    rem = value - rounded;
    if (rem < 0) {
        if (rem <= -scalePtr->resolution/2) {
            rounded = (tick - 1.0) * scalePtr->resolution;
        }
    } else {
        if (rem >= scalePtr->resolution/2) {
            rounded = (tick + 1.0) * scalePtr->resolution;
        }
    }
    return rounded;
}

/*
 *----------------------------------------------------------------------
 *
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
	    TCL_GLOBAL_ONLY);
    result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);
    if (result != TCL_OK) {
	resultStr = "can't assign non-numeric value to scale variable";
	ScaleSetVariable(scalePtr);
    } else {
	scalePtr->value = TkRoundToResolution(scalePtr, value);

	/*
	 * This code is a bit tricky because it sets the scale's value before
	 * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to
	 * set the variable again or to invoke the -command. However, it also
	 * won't redisplay the scale, so we have to ask for that explicitly.
	 */







|







1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
    valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
	    TCL_GLOBAL_ONLY);
    result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);
    if (result != TCL_OK) {
	resultStr = "can't assign non-numeric value to scale variable";
	ScaleSetVariable(scalePtr);
    } else {
	scalePtr->value = TkRoundValueToResolution(scalePtr, value);

	/*
	 * This code is a bit tricky because it sets the scale's value before
	 * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to
	 * set the variable again or to invoke the -command. However, it also
	 * won't redisplay the scale, so we have to ask for that explicitly.
	 */
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
    double value,		/* New value for scale. Gets adjusted if it's
				 * off the scale. */
    int setVar,			/* Non-zero means reflect new value through to
				 * associated variable, if any. */
    int invokeCommand)		/* Non-zero means invoked -command option to
				 * notify of new value, 0 means don't. */
{
    value = TkRoundToResolution(scalePtr, value);
    if ((value < scalePtr->fromValue)
	    ^ (scalePtr->toValue < scalePtr->fromValue)) {
	value = scalePtr->fromValue;
    }
    if ((value > scalePtr->toValue)
	    ^ (scalePtr->toValue < scalePtr->fromValue)) {
	value = scalePtr->toValue;







|







1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
    double value,		/* New value for scale. Gets adjusted if it's
				 * off the scale. */
    int setVar,			/* Non-zero means reflect new value through to
				 * associated variable, if any. */
    int invokeCommand)		/* Non-zero means invoked -command option to
				 * notify of new value, 0 means don't. */
{
    value = TkRoundValueToResolution(scalePtr, value);
    if ((value < scalePtr->fromValue)
	    ^ (scalePtr->toValue < scalePtr->fromValue)) {
	value = scalePtr->fromValue;
    }
    if ((value > scalePtr->toValue)
	    ^ (scalePtr->toValue < scalePtr->fromValue)) {
	value = scalePtr->toValue;
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
	value = 0;
    }
    if (value > 1) {
	value = 1;
    }
    value = scalePtr->fromValue +
		value * (scalePtr->toValue - scalePtr->fromValue);
    return TkRoundToResolution(scalePtr, value);
}

/*
 *----------------------------------------------------------------------
 *
 * TkScaleValueToPixel --
 *







|







1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
	value = 0;
    }
    if (value > 1) {
	value = 1;
    }
    value = scalePtr->fromValue +
		value * (scalePtr->toValue - scalePtr->fromValue);
    return TkRoundValueToResolution(scalePtr, value);
}

/*
 *----------------------------------------------------------------------
 *
 * TkScaleValueToPixel --
 *
Changes to generic/tkScale.h.
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
#define SPACING 2

/*
 * Declaration of procedures used in the implementation of the scale widget.
 */

MODULE_SCOPE void	TkEventuallyRedrawScale(TkScale *scalePtr, int what);
MODULE_SCOPE double	TkRoundToResolution(TkScale *scalePtr, double value);

MODULE_SCOPE TkScale *	TkpCreateScale(Tk_Window tkwin);
MODULE_SCOPE void	TkpDestroyScale(TkScale *scalePtr);
MODULE_SCOPE void	TkpDisplayScale(ClientData clientData);
MODULE_SCOPE int	TkpScaleElement(TkScale *scalePtr, int x, int y);
MODULE_SCOPE void	TkScaleSetValue(TkScale *scalePtr, double value,
			    int setVar, int invokeCommand);
MODULE_SCOPE double	TkScalePixelToValue(TkScale *scalePtr, int x, int y);







|
>







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#define SPACING 2

/*
 * Declaration of procedures used in the implementation of the scale widget.
 */

MODULE_SCOPE void	TkEventuallyRedrawScale(TkScale *scalePtr, int what);
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);
MODULE_SCOPE int	TkpScaleElement(TkScale *scalePtr, int x, int y);
MODULE_SCOPE void	TkScaleSetValue(TkScale *scalePtr, double value,
			    int setVar, int invokeCommand);
MODULE_SCOPE double	TkScalePixelToValue(TkScale *scalePtr, int x, int y);
Changes to generic/tkText.c.
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
    textPtr->refCount += 1;

    Tcl_Preserve((ClientData) textPtr->interp);
    if (!(textPtr->flags & DESTROYED)) {
	code = Tcl_EvalObjEx(textPtr->interp, afterSyncCmd, TCL_EVAL_GLOBAL);
	if (code == TCL_ERROR && !error) {
	    Tcl_AddErrorInfo(textPtr->interp, "\n    (text sync)");
	    Tcl_BackgroundError(textPtr->interp);
	    error = true;
	}
    }
    Tcl_GuardedDecrRefCount(afterSyncCmd);
    Tcl_Release((ClientData) textPtr->interp);
    TkTextDecrRefCountAndTestIfDestroyed(textPtr);
}







|







10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
    textPtr->refCount += 1;

    Tcl_Preserve((ClientData) textPtr->interp);
    if (!(textPtr->flags & DESTROYED)) {
	code = Tcl_EvalObjEx(textPtr->interp, afterSyncCmd, TCL_EVAL_GLOBAL);
	if (code == TCL_ERROR && !error) {
	    Tcl_AddErrorInfo(textPtr->interp, "\n    (text sync)");
	    Tcl_BackgroundException(textPtr->interp, TCL_ERROR);
	    error = true;
	}
    }
    Tcl_GuardedDecrRefCount(afterSyncCmd);
    Tcl_Release((ClientData) textPtr->interp);
    TkTextDecrRefCountAndTestIfDestroyed(textPtr);
}
Changes to library/menu.tcl.
229
230
231
232
233
234
235

236
237
238
239
240
241
242
    if {![winfo exists $w]} {
	return
    }
    if {[$w cget -state] eq "active" && [tk windowingsystem] ne "aqua"} {
	$w configure -state normal
    }
}


# ::tk::MbPost --
# Given a menubutton, this procedure does all the work of posting
# its associated menu and unposting any other menu that is currently
# posted.
#
# Arguments:







>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    if {![winfo exists $w]} {
	return
    }
    if {[$w cget -state] eq "active" && [tk windowingsystem] ne "aqua"} {
	$w configure -state normal
    }
}


# ::tk::MbPost --
# Given a menubutton, this procedure does all the work of posting
# its associated menu and unposting any other menu that is currently
# posted.
#
# Arguments:
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
	$w configure -state active
    }

    set Priv(postedMb) $w
    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]} {
	# 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} {
	focus $menu
	if {[winfo viewable $w]} {
	    SaveGrabInfo $w
	    grab -global $w
	}
    }
}







<
<
<
<
<

<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


<





|







279
280
281
282
283
284
285





286








287






































































288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
	$w configure -state active
    }

    set Priv(postedMb) $w
    set Priv(focus) [focus]
    $menu activate none
    GenerateMenuSelect $menu





    update idletasks















































































    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 && [tk windowingsystem] ne "aqua"} {
	focus $menu
	if {[winfo viewable $w]} {
	    SaveGrabInfo $w
	    grab -global $w
	}
    }
}
572
573
574
575
576
577
578


579
580
581
582
583
584
585
586
587
588
589
590
        if {[info exists Priv(menuActivated)] \
                && $index ne "none" \
                && $index ne $activeindex} {
            set mode [option get $menu clickToFocus ClickToFocus]
            if {[string is false $mode]} {
                set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}]
                if {[$menu type $index] eq "cascade"} {


                    set Priv(menuActivatedTimer) \
                        [after $delay [list $menu postcascade active]]
                } else {
                    set Priv(menuDeactivatedTimer) \
                        [after $delay [list $menu postcascade none]]
                }
            }
        }
    }
}

# ::tk::MenuButtonDown --







>
>

|


|







489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
        if {[info exists Priv(menuActivated)] \
                && $index ne "none" \
                && $index ne $activeindex} {
            set mode [option get $menu clickToFocus ClickToFocus]
            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 "catch {$menu postcascade active}"]
                } else {
                    set Priv(menuDeactivatedTimer) \
                        [after $delay "catch {$menu postcascade none}"]
                }
            }
        }
    }
}

# ::tk::MenuButtonDown --
1203
1204
1205
1206
1207
1208
1209
1210









































































































1211

1212

1213
1214

1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225

1226
1227

1228
1229
1230
1231
1232

1233




1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
	    if {$label eq $s} {
		return $i
	    }
	}
    }
    return ""
}










































































































# ::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.

#
# Arguments:
# menu -		Menu to post.
# x, y -		Root coordinates of point.
# entry -		Index of entry within menu to center over (x,y).
#			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}]

	} else {
	    incr y [expr {-([$menu yposition $entry] \
		    + [$menu yposition [expr {$entry+1}]])/2}]
	}
	incr x [expr {-[winfo reqwidth $menu]/2}]

    }





    if {[tk windowingsystem] eq "win32"} {
	# osVersion is not available in safe interps
	set ver 5
	if {[info exists ::tcl_platform(osVersion)]} {
	    scan $::tcl_platform(osVersion) %d ver
	}

	# We need to fix some problems with menu posting on Windows,
	# where, if the menu would overlap top or bottom of screen,
	# Windows puts it in the wrong place for us.  We must also
	# subtract an extra amount for half the height of the current
	# entry.  To be safe we subtract an extra 10.
	# NOTE: this issue appears to have been resolved in the Window
	# manager provided with Vista and Windows 7.
	if {$ver < 6} {
	    set yoffset [expr {[winfo screenheight $menu] \
		    - $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]}]
	    }
	    # If we're off the top of the screen (either because we were
	    # originally or because we just adjusted too far upwards),
	    # then make the menu popup on the top edge.
	    if {$y < [winfo vrooty $menu]} {
		set y [winfo vrooty $menu]
	    }
	}
    }
    $menu post $x $y
    if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
	$menu activate $entry
	GenerateMenuSelect $menu

    }
}

# ::tk::SaveGrabInfo --
# Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record
# the state of any existing grab on the w's display.
#








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
|
>








>
|
|
|
>
|
|
>

|
<

<
>

>
>
>
>
|
<















|











<
|
|
|
|
>







1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260

1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
	    if {$label eq $s} {
		return $i
	    }
	}
    }
    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 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.
# x, y -		Root coordinates of point.
# entry -		Index of entry within menu to center over (x,y).
#			If omitted or specified as {}, then the menu's
#			upper-left corner goes at (x,y).

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 {
	    $menu post $x $y

	}

	return
    }
} 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)]} {
	    scan $::tcl_platform(osVersion) %d ver
	}

	# We need to fix some problems with menu posting on Windows,
	# where, if the menu would overlap top or bottom of screen,
	# Windows puts it in the wrong place for us.  We must also
	# subtract an extra amount for half the height of the current
	# entry.  To be safe we subtract an extra 10.
	# NOTE: this issue appears to have been resolved in the Window
	# manager provided with Vista and Windows 7.
	if {$ver < 6} {
	    set yoffset [expr {[winfo screenheight $menu] \
				   - $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]}]
	    }
	    # If we're off the top of the screen (either because we were
	    # originally or because we just adjusted too far upwards),
	    # then make the menu popup on the top edge.
	    if {$y < [winfo vrooty $menu]} {
		set y [winfo vrooty $menu]
	    }
	}

	$menu post $x $y
	if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
	    $menu activate $entry
	    GenerateMenuSelect $menu
	}
    }
}

# ::tk::SaveGrabInfo --
# Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record
# the state of any existing grab on the w's display.
#
Changes to macosx/tkMacOSXDefault.h.
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#define DEF_MENU_TITLE			""
#define DEF_MENU_TYPE			"normal"

/*
 * Defaults for menubuttons:
 */

#define DEF_MENUBUTTON_ANCHOR		"center"
#define DEF_MENUBUTTON_ACTIVE_BG_COLOR	ACTIVE_BG
#define DEF_MENUBUTTON_ACTIVE_BG_MONO	BLACK
#define DEF_MENUBUTTON_ACTIVE_FG_COLOR	ACTIVE_FG
#define DEF_MENUBUTTON_ACTIVE_FG_MONO	WHITE
#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_CURSOR		""
#define DEF_MENUBUTTON_DIRECTION	"below"
#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
#define DEF_MENUBUTTON_DISABLED_FG_MONO	""
#define DEF_MENUBUTTON_FONT		"TkDefaultFont"
#define DEF_MENUBUTTON_FG		BLACK
#define DEF_MENUBUTTON_HEIGHT		"0"
#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR
#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO  DEF_MENUBUTTON_BG_MONO
#define DEF_MENUBUTTON_HIGHLIGHT	BLACK
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH	"0"
#define DEF_MENUBUTTON_IMAGE		NULL
#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_RELIEF		"flat"
#define DEF_MENUBUTTON_STATE		"normal"
#define DEF_MENUBUTTON_TAKE_FOCUS	"0"
#define DEF_MENUBUTTON_TEXT		""
#define DEF_MENUBUTTON_TEXT_VARIABLE	""
#define DEF_MENUBUTTON_UNDERLINE	"-1"
#define DEF_MENUBUTTON_WIDTH		"0"







|







|















|
|







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#define DEF_MENU_TITLE			""
#define DEF_MENU_TYPE			"normal"

/*
 * Defaults for menubuttons:
 */

#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
#define DEF_MENUBUTTON_ACTIVE_FG_MONO	WHITE
#define DEF_MENUBUTTON_BG_COLOR		NORMAL_BG
#define DEF_MENUBUTTON_BG_MONO		WHITE
#define DEF_MENUBUTTON_BITMAP		""
#define DEF_MENUBUTTON_BORDER_WIDTH	"0"
#define DEF_MENUBUTTON_CURSOR		""
#define DEF_MENUBUTTON_DIRECTION	"below"
#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
#define DEF_MENUBUTTON_DISABLED_FG_MONO	""
#define DEF_MENUBUTTON_FONT		"TkDefaultFont"
#define DEF_MENUBUTTON_FG		BLACK
#define DEF_MENUBUTTON_HEIGHT		"0"
#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR
#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO  DEF_MENUBUTTON_BG_MONO
#define DEF_MENUBUTTON_HIGHLIGHT	BLACK
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH	"0"
#define DEF_MENUBUTTON_IMAGE		NULL
#define DEF_MENUBUTTON_INDICATOR	"1"
#define DEF_MENUBUTTON_JUSTIFY		"left"
#define DEF_MENUBUTTON_MENU		""
#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"
#define DEF_MENUBUTTON_TEXT		""
#define DEF_MENUBUTTON_TEXT_VARIABLE	""
#define DEF_MENUBUTTON_UNDERLINE	"-1"
#define DEF_MENUBUTTON_WIDTH		"0"
Changes to macosx/tkMacOSXEmbed.c.
268
269
270
271
272
273
274







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
     */

    if (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) {
	return TCL_ERROR;
    }

    usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);







    if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"window \"%s\" doesn't have -container option set",
		usePtr->pathName));
	Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL);
	return TCL_ERROR;
    }

    /*
     * 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.
     */

    for (containerPtr = firstContainerPtr; containerPtr != NULL;
	    containerPtr = containerPtr->nextPtr) {
	if (containerPtr->parent == (Window) parent) {
	    winPtr->flags |= TK_BOTH_HALVES;
	    containerPtr->parentPtr->flags |= TK_BOTH_HALVES;







>
>
>
>
>
>
>
|








|
<
<
|
<
|
<
<
<







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291


292

293



294
295
296
297
298
299
300
     */

    if (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) {
	return TCL_ERROR;
    }

    usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);
    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));
	Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL);
	return TCL_ERROR;
    }

    /*
     * 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;
	    containerPtr = containerPtr->nextPtr) {
	if (containerPtr->parent == (Window) parent) {
	    winPtr->flags |= TK_BOTH_HALVES;
	    containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    macWin = ckalloc(sizeof(MacDrawable));
    if (macWin == NULL) {
	winPtr->privatePtr = NULL;
	return TCL_ERROR;
    }

    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;
    macWin->visRgn = NULL;
    macWin->aboveVisRgn = NULL;
    macWin->drawRgn = NULL;
    macWin->referenceCount = 0;
    macWin->flags = TK_CLIP_INVALID;
    macWin->toplevel = macWin;
    macWin->toplevel->referenceCount++;


    winPtr->flags |= TK_EMBEDDED;

    /*
     * Make a copy of the TK_EMBEDDED flag, since sometimes we need this to
     * get the port after the TkWindow structure has been freed.
     */

    macWin->flags |= TK_EMBEDDED;

    /*
     * 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.
     */

    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->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.
	 */

	Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
		winPtr);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
<
<
<
<
<
<
<











>








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|

|
|
|
|

|
|

|
|
|
|

|
|
<







309
310
311
312
313
314
315










316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335



































336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
    macWin = ckalloc(sizeof(MacDrawable));
    if (macWin == NULL) {
	winPtr->privatePtr = NULL;
	return TCL_ERROR;
    }

    macWin->winPtr = winPtr;










    macWin->view = nil;
    macWin->context = NULL;
    macWin->size = CGSizeZero;
    macWin->visRgn = NULL;
    macWin->aboveVisRgn = NULL;
    macWin->drawRgn = NULL;
    macWin->referenceCount = 0;
    macWin->flags = TK_CLIP_INVALID;
    macWin->toplevel = macWin;
    macWin->toplevel->referenceCount++;

    winPtr->privatePtr = macWin;
    winPtr->flags |= TK_EMBEDDED;

    /*
     * Make a copy of the TK_EMBEDDED flag, since sometimes we need this to
     * get the port after the TkWindow structure has been freed.
     */

    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;

    /*
     * 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.
     */

    Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
			  winPtr);


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The input focus may change.
 *







|
<
<







494
495
496
497
498
499
500
501


502
503
504
505
506
507
508

/*
 *----------------------------------------------------------------------
 *
 * TkpClaimFocus --
 *
 *	This procedure is invoked when someone asks for the input focus to be
 *	put on a window in an embedded application.


 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The input focus may change.
 *
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    event.xfocus.type = FocusIn;
    event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);
    event.xfocus.send_event = 1;
    event.xfocus.display = topLevelPtr->display;
    event.xfocus.window = containerPtr->parent;
    event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
    event.xfocus.detail = force;
    Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpTestembedCmd --
 *







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
    event.xfocus.type = FocusIn;
    event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);
    event.xfocus.send_event = 1;
    event.xfocus.display = topLevelPtr->display;
    event.xfocus.window = containerPtr->parent;
    event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
    event.xfocus.detail = force;
    Tk_HandleEvent(&event);
}

/*
 *----------------------------------------------------------------------
 *
 * TkpTestembedCmd --
 *
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625









626

627
628
629
630
631
632
633
634

635

636
637
638
639
640

641

642
643
644
645
646
647
648
649

650
651
652
653
654
655
656
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    Container *containerPtr;
    Tcl_DString dString;
    char buffer[50];


    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
	all = 1;
    } else {
	all = 0;
    }
    Tcl_DStringInit(&dString);
    for (containerPtr = firstContainerPtr; containerPtr != NULL;
	    containerPtr = containerPtr->nextPtr) {









	Tcl_DStringStartSublist(&dString);

	if (containerPtr->parent == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}

	if (containerPtr->parentPtr == NULL) {

	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->parentPtr->pathName);
	}

	if (containerPtr->embedded == None) {

	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->embedded);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	if (containerPtr->embeddedPtr == NULL) {

	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->embeddedPtr->pathName);
	}
	Tcl_DStringEndSublist(&dString);
    }







>









>
>
>
>
>
>
>
>
>

>








>
|
>





>
|
>
|
<
|
<
<
<
<
|
>







564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612




613
614
615
616
617
618
619
620
621
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    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;
    } else {
	all = 0;
    }
    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%" TCL_Z_MODIFIER "x", (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	/* Parent pathName */
	if (containerPtr->parentPtr == NULL ||
	    parentInterp != interp) {
	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->parentPtr->pathName);
	}
	/*
	 * 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,
		    containerPtr->embeddedPtr->pathName);
	}
	Tcl_DStringEndSublist(&dString);
    }
900
901
902
903
904
905
906








907
908
909
910
911
912
913
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;
    Tk_ErrorHandler errHandler;

    if (eventPtr->type == ConfigureNotify) {








	if (containerPtr->embedded != None) {
	    /*
	     * Ignore errors, since the embedded application could have
	     * deleted its window.
	     */

	    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,







>
>
>
>
>
>
>
>







865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;
    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
	     * deleted its window.
	     */

	    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

static void
EmbedActivateProc(
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;

    if (containerPtr->embeddedPtr != NULL) {
	if (eventPtr->type == ActivateNotify) {
	    TkGenerateActivateEvents(containerPtr->embeddedPtr,1);
	} else if (eventPtr->type == DeactivateNotify) {
	    TkGenerateActivateEvents(containerPtr->embeddedPtr,0);
	}
    }







<







916
917
918
919
920
921
922

923
924
925
926
927
928
929

static void
EmbedActivateProc(
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;

    if (containerPtr->embeddedPtr != NULL) {
	if (eventPtr->type == ActivateNotify) {
	    TkGenerateActivateEvents(containerPtr->embeddedPtr,1);
	} else if (eventPtr->type == DeactivateNotify) {
	    TkGenerateActivateEvents(containerPtr->embeddedPtr,0);
	}
    }
Changes to macosx/tkMacOSXEvent.c.
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXFlushWindows --
 *
 *	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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Calls the drawRect method of the contentView of each visible
 *      window.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
    NSArray *macWindows = [NSApp orderedWindows];


    if ([macWindows count] > 0) {
	while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
    }
    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];
	    }
	}
    }
}


/*
 * Local Variables:
 * mode: objc







|
|
|
|
<
<
<
<




|
<
|







|
>
|
<
|
<
<
|
<
<
<
<
<
<
<
|
<
<







110
111
112
113
114
115
116
117
118
119
120




121
122
123
124
125

126
127
128
129
130
131
132
133
134
135
136

137


138







139


140
141
142
143
144
145
146
/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXFlushWindows --
 *
 *	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 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: Processes all pending idle events then calls the display

 *	method of each visible window.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
    if (Tk_GetNumMainWindows() == 0) {
	return;
    }

    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}


    for (NSWindow *w in [NSApp orderedWindows]) {







	[w display];


    }
}


/*
 * Local Variables:
 * mode: objc
Changes to macosx/tkMacOSXMenu.c.
751
752
753
754
755
756
757
758



759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789





790
791
792
793
794
795
796
797
798


799
800

801
802
803
804
805




806
807
808
809

810
811
812
813

814
815
816
817
818
819







































































































820
821
822
823
824
825
826
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	Posts a menu on the screen



 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

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 */
{


    /* 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;

    inPostMenu = 1;

    result = TkPreprocessMenu(menuPtr);
    if (result != TCL_OK) {
        inPostMenu = 0;
        return result;
    }



    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];





    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);
    inPostMenu = 0;
    return TCL_OK;
}








































































































/*
 *----------------------------------------------------------------------
 *
 * TkpSetWindowMenuBar --
 *
 *	Associates a given menu with a window.







|
>
>
>


|











|
|
|
|

|
<
<
|
|



<



>
>
>
>
>
|


<





>
>
|
<
>
|
<
|
|
<
>
>
>
>

|
<
<
>
|
|
|
<
>
|
<
<



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781


782
783
784
785
786

787
788
789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805

806
807

808
809

810
811
812
813
814
815


816
817
818
819

820
821


822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	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:
 *	Returns a standard Tcl result.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,		/* The interpreter this menu lives in */
    TkMenu *menuPtr,		/* The menu we are posting */
    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);

    if (root == NULL) {
	return TCL_ERROR;
    }

    Drawable d = Tk_WindowId(root);
    NSView *rootview = TkMacOSXGetRootControl(d);
    NSWindow *win = [rootview window];
    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.
     */

    if (menuPtr->tkwin == NULL) {


    	return TCL_OK;
    }

    [menu popUpMenuPositioningItem:item

			atLocation:[win tkConvertPointFromScreen:location]
			    inView:view];


    inPostMenu = 0;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
873
874
875
876
877
878
879

880




881
882

883



884
885
886
887
888







889
890
891
892
893
894
895
896
897
898
899







900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
TkpSetMainMenubar(
    Tcl_Interp *interp,		/* The interpreter of the application */
    Tk_Window tkwin,		/* The frame we are setting up */
    const char *menuName)	/* The name of the menu to put in front. */
{
    static Tcl_Interp *currentInterp = NULL;
    TKMenu *menu = nil;






    if (menuName) {
	TkWindow *winPtr = (TkWindow *) tkwin;





	if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
		winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
		winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
		!strcmp(menuName, Tk_PathName(
		winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {







	    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 (menu || interp != currentInterp) {
	[NSApp tkSetMainMenu:menu];
    }
    currentInterp = interp;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Will set entryFlags appropriately.
 *







>

>
>
>
>
|
|
>
|
>
>
>
|
|
|
<
|
>
>
>
>
>
>
>




<






>
>
>
>
>
>
>












|
|







981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
TkpSetMainMenubar(
    Tcl_Interp *interp,		/* The interpreter of the application */
    Tk_Window tkwin,		/* The frame we are setting up */
    const char *menuName)	/* The name of the menu to put in front. */
{
    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) {
	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 (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];
    }
    currentInterp = interp;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Will set entryFlags appropriately.
 *
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099



1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
 *--------------------------------------------------------------
 */

void
TkpComputeStandardMenuGeometry(
    TkMenu *menuPtr)		/* Structure describing menu. */
{

    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 entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
    TkMenuEntry *mePtr, *columnEntryPtr;
    int haveAccel = 0;




    if (menuPtr->tkwin == NULL) {
	return;
    }


    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
	    &borderWidth);
    Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
	    &activeBorderWidth);
    x = y = borderWidth;
    windowHeight = maxWidth = lastColumnBreak = 0;
    maxIndicatorSpace = 0;

    /*
     * On the Mac especially, getting font metrics can be quite slow, so we
     * want to do it intelligently. We are going to precalculate them and pass
     * them down to all of the measuring and drawing routines. We will measure
     * the font metrics of the menu once. If an entry does not have its own







>





|

|


>
>
>
|


|
>





|







1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
 *--------------------------------------------------------------
 */

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, maxWidth;
    int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
    TkMenuEntry *mePtr;
    int haveAccel = 0;

    /*
     * 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 = 0;
    maxIndicatorSpace = 0;

    /*
     * On the Mac especially, getting font metrics can be quite slow, so we
     * want to do it intelligently. We are going to precalculate them and pass
     * them down to all of the measuring and drawing routines. We will measure
     * the font metrics of the menu once. If an entry does not have its own
1129
1130
1131
1132
1133
1134
1135



1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219



1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
	    haveAccel = 1;
	    break;
	}
    }

    for (i = 0; i < menuPtr->numEntries; i++) {
	mePtr = menuPtr->entries[i];



	if (mePtr->fontPtr == NULL) {
	    tkfont = menuFont;
	    fmPtr = &menuMetrics;
	    modifierCharWidth = menuModifierCharWidth;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
	    Tk_GetFontMetrics(tkfont, &entryMetrics);
	    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) {
	    mePtr->height = menuSeparatorHeight;
	} else {
	    /*
	     * For each entry, compute the height required by that particular
	     * entry, plus three widths: the width of the label, the width to
	     * allow for an indicator to be displayed to the left of the label
	     * (if any), and the width of the accelerator to be displayed to
	     * the right of the label (if any). These sizes depend, of course,
	     * on the type of the entry.
	     */

	    NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
	    int haveImage = 0, width = 0, height = 0;

	    if (mePtr->image) {
		Tk_SizeOfImage(mePtr->image, &width, &height);
		haveImage = 1;

	    } else if (mePtr->bitmapPtr) {
		Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
			mePtr->bitmapPtr);

		Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
		haveImage = 1;

	    }
	    if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
		NSAttributedString *attrTitle = [menuItem attributedTitle];
		NSSize size;

		if (attrTitle) {
		    size = [attrTitle size];
		} else {
		    size = [[menuItem title] sizeWithAttributes:
			TkMacOSXNSFontAttributesForFont(tkfont)];
		}
		size.width += menuTextLeadingEdgeMargin +
			menuTextTrailingEdgeMargin;
		if (size.height < fmPtr->linespace) {
		    size.height = fmPtr->linespace;
		}
		if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
		    int margin = width + menuIconTrailingEdgeMargin;

		    if (margin > menuTextLeadingEdgeMargin) {
			margin = menuTextLeadingEdgeMargin;
		    }
		    width += size.width + menuIconTrailingEdgeMargin - margin;
		    if (size.height > height) {
			height = size.height;
		    }
		} else {
		    width = size.width;
		    height = size.height;
		}
	    }



	    labelWidth = width + menuItemExtraWidth;
	    mePtr->height = height + menuItemExtraHeight;

	    if (mePtr->type == CASCADE_ENTRY) {
		modifierWidth = modifierCharWidth;
	    } else if (mePtr->accelLength == 0) {
		if (haveAccel && !mePtr->hideMargin) {
		    modifierWidth = modifierCharWidth;
		}
	    } else {







>
>
>










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|













<



>



<


>











|
<
<
|
<















>
>
>


<







1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282


















1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297

1298
1299
1300
1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319


1320

1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
	    haveAccel = 1;
	    break;
	}
    }

    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;
	    modifierCharWidth = menuModifierCharWidth;
	} else {
	    tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
	    Tk_GetFontMetrics(tkfont, &entryMetrics);
	    fmPtr = &entryMetrics;
	    modifierCharWidth = ModifierCharWidth(tkfont);
	}


















	accelWidth = modifierWidth = indicatorSpace = 0;
	if (mePtr->type == SEPARATOR_ENTRY) {
	    mePtr->height = menuSeparatorHeight;
	} else {
	    /*
	     * For each entry, compute the height required by that particular
	     * entry, plus three widths: the width of the label, the width to
	     * allow for an indicator to be displayed to the left of the label
	     * (if any), and the width of the accelerator to be displayed to
	     * the right of the label (if any). These sizes depend, of course,
	     * on the type of the entry.
	     */

	    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];
		NSSize size;

		if (attrTitle) {
		    size = [attrTitle size];
		} else {
		    size = [[menuItem title] sizeWithAttributes:
			TkMacOSXNSFontAttributesForFont(tkfont)];
		}
		size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;


		size.height -= 1; /* tweak */

		if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
		    int margin = width + menuIconTrailingEdgeMargin;

		    if (margin > menuTextLeadingEdgeMargin) {
			margin = menuTextLeadingEdgeMargin;
		    }
		    width += size.width + menuIconTrailingEdgeMargin - margin;
		    if (size.height > height) {
			height = size.height;
		    }
		} else {
		    width = size.width;
		    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) {
		if (haveAccel && !mePtr->hideMargin) {
		    modifierWidth = modifierCharWidth;
		}
	    } else {
1246
1247
1248
1249
1250
1251
1252

1253
1254

1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
	    if (indicatorSpace > maxIndicatorSpace) {
		maxIndicatorSpace = indicatorSpace;
	    }
	    entryWidth = labelWidth + modifierWidth + accelWidth;
	    if (entryWidth > maxWidth) {
		maxWidth = entryWidth;
	    }

	    mePtr->height += 2 * activeBorderWidth;
	}

	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;

    if (windowWidth <= 0) {
	windowWidth = 1;
    }

    if (windowHeight <= 0) {
	windowHeight = 1;
    }
    menuPtr->totalWidth = windowWidth;
    menuPtr->totalHeight = windowHeight;
}








>


>


<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<



>







1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376


1377










1378



1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
	    if (indicatorSpace > maxIndicatorSpace) {
		maxIndicatorSpace = indicatorSpace;
	    }
	    entryWidth = labelWidth + modifierWidth + accelWidth;
	    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;


    }










    windowWidth = menuSize.width;



    if (windowWidth <= 0) {
	windowWidth = 1;
    }
    windowHeight = menuSize.height;
    if (windowHeight <= 0) {
	windowHeight = 1;
    }
    menuPtr->totalWidth = windowWidth;
    menuPtr->totalHeight = windowHeight;
}

Changes to macosx/tkMacOSXMenubutton.c.
43
44
45
46
47
48
49
50
51
52
53
54

55



56
57


58

59
60
61
62
63
64
65
66
67
68
69
70
71
72






73




























74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    ThemeButtonKind btnkind;
    HIThemeButtonDrawInfo drawinfo;
    HIThemeButtonDrawInfo lastdrawinfo;
    DrawParams drawParams;
} MacMenuButton;

/*
 * Forward declarations for procedures 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 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 DrawMenuButtonImageAndText(TkMenuButton* butPtr);

/*
 * The structure below defines menubutton class behavior by means of
 * procedures that can be invoked from generic window code.
 */

Tk_ClassProcs tkpMenubuttonClass = {
    sizeof(Tk_ClassProcs),	/* size */
    TkMenuButtonWorldChanged,	/* worldChangedProc */
};




































/*
 *----------------------------------------------------------------------
 *
 * TkpCreateMenuButton --
 *
 *	Allocate a new TkMenuButton structure.
 *
 * Results:
 *	Returns a newly allocated TkMenuButton structure.
 *
 * Side effects:
 *	Registers an event handler for the widget.
 *
 *----------------------------------------------------------------------
 */

TkMenuButton *
TkpCreateMenuButton(
    Tk_Window tkwin)
{
    MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));

    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;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayMenuButton --







|



|
>
|
>
>
>

|
>
>
|
>
|
<












>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|


















|
|




<







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
    ThemeButtonKind btnkind;
    HIThemeButtonDrawInfo drawinfo;
    HIThemeButtonDrawInfo lastdrawinfo;
    DrawParams drawParams;
} MacMenuButton;

/*
 * 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 MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr);
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);

/*
 * The structure below defines menubutton class behavior by means of
 * procedures that can be invoked from generic window code.
 */

Tk_ClassProcs tkpMenubuttonClass = {
    sizeof(Tk_ClassProcs),	/* size */
    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  --
 *
 *	Allocate a new TkMenuButton structure.
 *
 * Results:
 *	Returns a newly allocated TkMenuButton structure.
 *
 * Side effects:
 *	Registers an event handler for the widget.
 *
 *----------------------------------------------------------------------
 */

TkMenuButton *
TkpCreateMenuButton(
    Tk_Window tkwin)
{
    MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));

    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;
}

/*
 *----------------------------------------------------------------------
 *
 * TkpDisplayMenuButton --
161
162
163
164
165
166
167

168
169
170
171
172
173
174
175
176
177
178
179
180

/*
 *----------------------------------------------------------------------
 *
 * TkpDestroyMenuButton --
 *
 *	Free data structures associated with the menubutton control.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Restores the default control state.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuButton(
    TkMenuButton *mbPtr)







>





|







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

/*
 *----------------------------------------------------------------------
 *
 * TkpDestroyMenuButton --
 *
 *	Free data structures associated with the menubutton control.
 *      This is a no-op on the Mac.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TkpDestroyMenuButton(
    TkMenuButton *mbPtr)
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
 */

void
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;


    /*
     * First figure out the size of the contents of the button.
     */

    width = 0;
    height = 0;
    txtWidth = 0;
    txtHeight = 0;
    avgWidth = 0;

    TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);

    if (butPtr->image != NULL) {
        Tk_SizeOfImage(butPtr->image, &width, &height);
        haveImage = 1;
    } else if (butPtr->bitmap != None) {
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
        haveImage = 1;
    }

    if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {

        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);
    }

    /*
     * If the button is compound (ie, it shows both an image and text),
     * the new geometry is a combination of the image and text geometry.
     * We only honor the compound bit if the button has both text and an
     * image, because otherwise it is not really a compound button.
     */

    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
        switch ((enum compound) butPtr->compound) {
            case COMPOUND_TOP:
            case COMPOUND_BOTTOM: {
                /*
                 * Image is above or below text
                 */








<


<
<
<
>


|








<
<








|
>




<




<









|







240
241
242
243
244
245
246

247
248



249
250
251
252
253
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
269
270
271
272
273
274

275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
 */

void
TkpComputeMenuButtonGeometry(butPtr)
    register TkMenuButton *butPtr;	/* Widget record for menu button. */
{
    int width, height, avgWidth, haveImage = 0, haveText = 0;

    int txtWidth, txtHeight;
    Tk_FontMetrics fm;



    int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;

    /*
     * First compute the size of the contents of the button.
     */

    width = 0;
    height = 0;
    txtWidth = 0;
    txtHeight = 0;
    avgWidth = 0;



    if (butPtr->image != NULL) {
        Tk_SizeOfImage(butPtr->image, &width, &height);
        haveImage = 1;
    } else if (butPtr->bitmap != None) {
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
        haveImage = 1;
    }

    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);

    }

    /*
     * If the button is compound (ie, it shows both an image and text),
     * the new geometry is a combination of the image and text geometry.
     * We only honor the compound bit if the button has both text and an
     * image, because otherwise it is not really a compound button.
     */

    if (haveImage && haveText) {
        switch ((enum compound) butPtr->compound) {
            case COMPOUND_TOP:
            case COMPOUND_BOTTOM: {
                /*
                 * Image is above or below text
                 */

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
            width = butPtr->width;
        }
        if (butPtr->height > 0) {
            height = butPtr->height;
        }

    } else {
        if (haveImage) {
            if (butPtr->width > 0) {
                width = butPtr->width;
            }
            if (butPtr->height > 0) {
                height = butPtr->height;
            }
        } else {
            width = txtWidth;
            height = txtHeight;
            if (butPtr->width > 0) {
                width = butPtr->width * avgWidth;
            }
            if (butPtr->height > 0) {
                height = butPtr->height * fm.linespace;
            }
        }
    }
    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;


    Tk_GeometryRequest(butPtr->tkwin, width, height);
    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}

/*
 *----------------------------------------------------------------------
 *







|






|



|


|



<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347


348










349

350





























351

352




353
354
355
356
357
358
359
            width = butPtr->width;
        }
        if (butPtr->height > 0) {
            height = butPtr->height;
        }

    } else {
        if (haveImage) { /* Image only */
            if (butPtr->width > 0) {
                width = butPtr->width;
            }
            if (butPtr->height > 0) {
                height = butPtr->height;
            }
        } else { /* Text only */
            width = txtWidth;
            height = txtHeight;
            if (butPtr->width > 0) {
                width = butPtr->width * avgWidth + 2*butPtr->padX;
            }
            if (butPtr->height > 0) {
                height = butPtr->height * fm.linespace + 2*butPtr->padY;
            }
        }
    }


    










    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);
}

/*
 *----------------------------------------------------------------------
 *
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
    imageHeight = height;

    if (mbPtr->drawinfo.state == kThemeStatePressed) {
        /* Offset bitmaps by a bit when the button is pressed. */
        pressed = 1;
    }

  haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
   if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
        int x = 0;
        int y = 0;
        textXOffset = 0;
        textYOffset = 0;
        fullWidth = 0;
        fullHeight = 0;

        switch ((enum compound) butPtr->compound) {
            case COMPOUND_TOP:
            case COMPOUND_BOTTOM: {
                /* Image is above or below text */
                if (butPtr->compound == COMPOUND_TOP) {
                    textYOffset = height + butPtr->padY;
                } else {
                    imageYOffset = butPtr->textHeight + butPtr->padY;
                }
                fullHeight = height + butPtr->textHeight + butPtr->padY;
                fullWidth = (width > butPtr->textWidth ? width :
                        butPtr->textWidth);
                textXOffset = (fullWidth - butPtr->textWidth)/2;
                imageXOffset = (fullWidth - width)/2;
                break;
            }
            case COMPOUND_LEFT:
            case COMPOUND_RIGHT: {
                /*







|
|

















|
|







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
    imageHeight = height;

    if (mbPtr->drawinfo.state == kThemeStatePressed) {
        /* Offset bitmaps by a bit when the button is pressed. */
        pressed = 1;
    }

    haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
    if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
        int x = 0;
        int y = 0;
        textXOffset = 0;
        textYOffset = 0;
        fullWidth = 0;
        fullHeight = 0;

        switch ((enum compound) butPtr->compound) {
            case COMPOUND_TOP:
            case COMPOUND_BOTTOM: {
                /* Image is above or below text */
                if (butPtr->compound == COMPOUND_TOP) {
                    textYOffset = height + butPtr->padY;
                } else {
                    imageYOffset = butPtr->textHeight + butPtr->padY;
                }
                fullHeight = height + butPtr->textHeight + butPtr->padY;
                fullWidth = (width > butPtr->textWidth ?
			     width : butPtr->textWidth);
                textXOffset = (fullWidth - butPtr->textWidth)/2;
                imageXOffset = (fullWidth - width)/2;
                break;
            }
            case COMPOUND_LEFT:
            case COMPOUND_RIGHT: {
                /*
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
                imageYOffset = (fullHeight - height)/2;
                break;
            }
            case COMPOUND_NONE: {break;}
	}

        TkComputeAnchor(butPtr->anchor, tkwin,
                butPtr->padX + butPtr->borderWidth,
                butPtr->padY + butPtr->borderWidth,
                fullWidth, fullHeight, &x, &y);
        imageXOffset += x;
        imageYOffset += y;
        textYOffset -= 1;

        if (butPtr->image != NULL) {
                Tk_RedrawImage(butPtr->image, 0, 0, width,
                        height, pixmap, imageXOffset, imageYOffset);
        } else {







|
|

|







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
                imageYOffset = (fullHeight - height)/2;
                break;
            }
            case COMPOUND_NONE: {break;}
	}

        TkComputeAnchor(butPtr->anchor, tkwin,
                butPtr->padX + butPtr->inset,
                butPtr->padY + butPtr->inset,
                fullWidth, fullHeight, &x, &y);
        imageXOffset = LEFT_INSET;
        imageYOffset += y;
        textYOffset -= 1;

        if (butPtr->image != NULL) {
                Tk_RedrawImage(butPtr->image, 0, 0, width,
                        height, pixmap, imageXOffset, imageYOffset);
        } else {
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
                x + textXOffset, y + textYOffset, 0, -1);
        Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
                butPtr->textLayout,
                x + textXOffset, y + textYOffset,
                butPtr->underline);
    } else {
        if (haveImage) {
            int x = 0;
            int 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);
            } 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);
                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;
	    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);
	    y += butPtr->textHeight/2;
	  }
   }
}










<
|




|
|
<
|
|
|



|
|
|
|



<
<
|
|



|







500
501
502
503
504
505
506

507
508
509
510
511
512
513

514
515
516
517
518
519
520
521
522
523
524
525
526


527
528
529
530
531
532
533
534
535
536
537
538
539
                x + textXOffset, y + textYOffset, 0, -1);
        Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
                butPtr->textLayout,
                x + textXOffset, y + textYOffset,
                butPtr->underline);
    } else {
        if (haveImage) {

            int x, y;
            TkComputeAnchor(butPtr->anchor, tkwin,
                    butPtr->padX + butPtr->borderWidth,
                    butPtr->padY + butPtr->borderWidth,
                    width, height, &x, &y);
	    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);
                XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
            }
        } else {


	    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, textXOffset, y, 0, -1);
	    y += butPtr->textHeight/2;
	  }
   }
}



574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
static void
TkMacOSXDrawMenuButton(
    MacMenuButton *mbPtr, /* Mac menubutton. */
    GC gc,                /* The GC we are drawing into - needed for
                           * the bevel button */
    Pixmap pixmap)        /* The pixmap we are drawing into - needed
                           * for the bevel button */

{
    TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
    TkWindow * winPtr;
    HIRect       cntrRect;
    TkMacOSXDrawingContext dc;
    DrawParams* dpPtr = &mbPtr->drawParams;
    int useNewerHITools = 1;

    winPtr = (TkWindow *)butPtr->tkwin;

    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);


    if (useNewerHITools == 1) {
        HIRect contHIRec;
        static HIThemeButtonDrawInfo hiinfo;

        MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true);








<












|
|
<
|







557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
585
static void
TkMacOSXDrawMenuButton(
    MacMenuButton *mbPtr, /* Mac menubutton. */
    GC gc,                /* The GC we are drawing into - needed for
                           * the bevel button */
    Pixmap pixmap)        /* The pixmap we are drawing into - needed
                           * for the bevel button */

{
    TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
    TkWindow * winPtr;
    HIRect       cntrRect;
    TkMacOSXDrawingContext dc;
    DrawParams* dpPtr = &mbPtr->drawParams;
    int useNewerHITools = 1;

    winPtr = (TkWindow *)butPtr->tkwin;

    TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);

    cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
			  Tk_Width(butPtr->tkwin),

			  Tk_Height(butPtr->tkwin));

    if (useNewerHITools == 1) {
        HIRect contHIRec;
        static HIThemeButtonDrawInfo hiinfo;

        MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true);

613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632
633
634
635
636
637
        hiinfo.value = mbPtr->drawinfo.value;
        hiinfo.adornment = mbPtr->drawinfo.adornment;
        hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
        if (hiinfo.animation.time.start == 0) {
            hiinfo.animation.time.start = hiinfo.animation.time.current;
        }

        HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);

	TkMacOSXRestoreDrawingContext(&dc);

        MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true);

    } else {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	    return;
	}


	TkMacOSXRestoreDrawingContext(&dc);
    }
    mbPtr->lastdrawinfo = mbPtr->drawinfo;
}

/*
 *--------------------------------------------------------------







|
|

<
|
>




<
<







594
595
596
597
598
599
600
601
602
603

604
605
606
607
608
609


610
611
612
613
614
615
616
        hiinfo.value = mbPtr->drawinfo.value;
        hiinfo.adornment = mbPtr->drawinfo.adornment;
        hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
        if (hiinfo.animation.time.start == 0) {
            hiinfo.animation.time.start = hiinfo.animation.time.current;
        }

        HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
			  kHIThemeOrientationNormal, &contHIRec);
	TkMacOSXRestoreDrawingContext(&dc);

        MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo,
				 (MacMenuButton *)mbPtr, 32, true);
    } else {
	if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
	    return;
	}


	TkMacOSXRestoreDrawingContext(&dc);
    }
    mbPtr->lastdrawinfo = mbPtr->drawinfo;
}

/*
 *--------------------------------------------------------------
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
{
    TkMenuButton  *butPtr = (TkMenuButton *)ptr;
    Tk_Window  tkwin  = butPtr->tkwin;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }

    DrawMenuButtonImageAndText( butPtr);
}

/*
 *--------------------------------------------------------------
 *
 * MenuButtonEventProc --
 *







<
|







671
672
673
674
675
676
677

678
679
680
681
682
683
684
685
{
    TkMenuButton  *butPtr = (TkMenuButton *)ptr;
    Tk_Window  tkwin  = butPtr->tkwin;

    if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
        return;
    }

    DrawMenuButtonImageAndText(butPtr);
}

/*
 *--------------------------------------------------------------
 *
 * MenuButtonEventProc --
 *
757
758
759
760
761
762
763
764



765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
 * Side effects:
 *        Sets the btnkind and drawinfo parameters
 *
 *----------------------------------------------------------------------
 */

static void
TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo)



{
    MacMenuButton *mbPtr = (MacMenuButton *)butPtr;

    if (butPtr->image || butPtr->bitmap) {
	/* TODO: allow for Small and Mini menubuttons. */
	*btnkind = kThemePopupButton;
    } else {
        if (!butPtr->text || !*butPtr->text) {
            *btnkind = kThemeArrowButton;
        } else {
            *btnkind = kThemePopupButton;
        }
    }

    drawinfo->value = kThemeButtonOff;

    if ((mbPtr->flags & FIRST_DRAW) != 0) {
	mbPtr->flags &= ~FIRST_DRAW;
	if (Tk_MacOSXIsAppInFront()) {







|
>
>
>



|


|
<
|
<
<
<







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752

753



754
755
756
757
758
759
760
 * Side effects:
 *        Sets the btnkind and drawinfo parameters
 *
 *----------------------------------------------------------------------
 */

static void
TkMacOSXComputeMenuButtonParams(
    TkMenuButton * butPtr,
    ThemeButtonKind* btnkind,
    HIThemeButtonDrawInfo *drawinfo)
{
    MacMenuButton *mbPtr = (MacMenuButton *)butPtr;

    if (butPtr->image || butPtr->bitmap || butPtr->text) {
	/* TODO: allow for Small and Mini menubuttons. */
	*btnkind = kThemePopupButton;
    } else { /* This should never happen. */

	*btnkind = kThemeArrowButton;



    }

    drawinfo->value = kThemeButtonOff;

    if ((mbPtr->flags & FIRST_DRAW) != 0) {
	mbPtr->flags &= ~FIRST_DRAW;
	if (Tk_MacOSXIsAppInFront()) {
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829


830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXComputeMenuButtonDrawParams --
 *
 *        This procedure computes the various parameters used
 *        when drawing a button
 *      These are determined by the various tk button parameters
 *
 * Results:
 *        1 if control will be used, 0 otherwise.
 *
 * Side effects:
 *        Sets the button draw parameters
 *
 *----------------------------------------------------------------------
 */

static int
TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)


{
    dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
            || (butPtr->bitmap != None));
    dpPtr->border = butPtr->normalBorder;
    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
        dpPtr->gc = butPtr->disabledGC;
    } else if (butPtr->state == STATE_ACTIVE) {
        dpPtr->gc = butPtr->activeTextGC;
        dpPtr->border = butPtr->activeBorder;
    } else {
        dpPtr->gc = butPtr->normalTextGC;
    }

    return 1;
}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */







|
|
<


|


|




|
|
>
>

|
|









<
<










785
786
787
788
789
790
791
792
793

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819


820
821
822
823
824
825
826
827
828
829
}

/*
 *----------------------------------------------------------------------
 *
 * TkMacOSXComputeMenuButtonDrawParams --
 *
 *        This procedure selects an appropriate drawing context for
 *        drawing a menubutton.

 *
 * Results:
 *        None.
 *
 * Side effects:
 *        Sets the button draw parameters.
 *
 *----------------------------------------------------------------------
 */

static void
TkMacOSXComputeMenuButtonDrawParams(
    TkMenuButton * butPtr,
    DrawParams * dpPtr)
{
    dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) ||
			       (butPtr->bitmap != None));
    dpPtr->border = butPtr->normalBorder;
    if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
        dpPtr->gc = butPtr->disabledGC;
    } else if (butPtr->state == STATE_ACTIVE) {
        dpPtr->gc = butPtr->activeTextGC;
        dpPtr->border = butPtr->activeBorder;
    } else {
        dpPtr->gc = butPtr->normalTextGC;
    }


}

/*
 * Local Variables:
 * mode: objc
 * c-basic-offset: 4
 * fill-column: 79
 * coding: utf-8
 * End:
 */
Changes to macosx/tkMacOSXSend.c.
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
int
Tk_SendObjCmd(
    ClientData clientData,	/* Used only for deletion */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* The arguments */
{
    const char *const sendOptions[] = {"-async", "-displayof", "-", NULL};
    char *stringRep, *destName;
    /*int async = 0;*/
    int i, index, firstArg;
    RegisteredInterp *riPtr;
    Tcl_Obj *listObjPtr;
    int result = TCL_OK;








|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
int
Tk_SendObjCmd(
    ClientData clientData,	/* Used only for deletion */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* The arguments */
{
    const char *const sendOptions[] = {"-async", "-displayof", "--", NULL};
    char *stringRep, *destName;
    /*int async = 0;*/
    int i, index, firstArg;
    RegisteredInterp *riPtr;
    Tcl_Obj *listObjPtr;
    int result = TCL_OK;

Changes to macosx/tkMacOSXSubwindows.c.
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

/*
 *----------------------------------------------------------------------
 *
 * UpdateOffsets --
 *
 *	Updates the X & Y offsets of the given TkWindow from the TopLevel it is
 *	a decendant of.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The xOff & yOff fields for the Mac window datastructure is updated to
 *	the proper offset.







|







1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324

/*
 *----------------------------------------------------------------------
 *
 * UpdateOffsets --
 *
 *	Updates the X & Y offsets of the given TkWindow from the TopLevel it is
 *	a descendant of.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The xOff & yOff fields for the Mac window datastructure is updated to
 *	the proper offset.
Changes to macosx/tkMacOSXWindowEvent.c.
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
			 isEqualToString:NSWindowDidMoveNotification];
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    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);
	if (winPtr->changes.x != x || winPtr->changes.y != y) {
	    flags |= TK_LOCATION_CHANGED;
	} else {
	    x = y = -1;
	}
	if (!movedOnly && (winPtr->changes.width != bounds.size.width ||
		winPtr->changes.height !=  bounds.size.height)) {
	    width = bounds.size.width - wmPtr->xInParent;
	    height = bounds.size.height - wmPtr->yInParent;
	    flags |= TK_SIZE_CHANGED;
	}
	if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {

	    /*
	     * Propagate geometry changes immediately.
	     */

	    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);
    }

}

- (void) windowExpanded: (NSNotification *) notification
{







<

<


|




















<
<
<
<
<
<
<
<
<
<
<
<
<
<







71
72
73
74
75
76
77

78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101














102
103
104
105
106
107
108
			 isEqualToString:NSWindowDidMoveNotification];
    NSWindow *w = [notification object];
    TkWindow *winPtr = TkMacOSXGetTkWindow(w);

    if (winPtr) {
	WmInfo *wmPtr = winPtr->wmInfoPtr;
	NSRect bounds = [w frame];

	int x, y, width = -1, height = -1, flags = 0;


	x = bounds.origin.x;
	y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
	if (winPtr->changes.x != x || winPtr->changes.y != y) {
	    flags |= TK_LOCATION_CHANGED;
	} else {
	    x = y = -1;
	}
	if (!movedOnly && (winPtr->changes.width != bounds.size.width ||
		winPtr->changes.height !=  bounds.size.height)) {
	    width = bounds.size.width - wmPtr->xInParent;
	    height = bounds.size.height - wmPtr->yInParent;
	    flags |= TK_SIZE_CHANGED;
	}
	if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {

	    /*
	     * Propagate geometry changes immediately.
	     */

	    flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
	}















	TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
    }

}

- (void) windowExpanded: (NSNotification *) notification
{
519
520
521
522
523
524
525

526

527
528
529
530
531
532
533

int
GenerateActivateEvents(
    TkWindow *winPtr,
    int activeFlag)
{
    TkGenerateActivateEvents(winPtr, activeFlag);

    TkMacOSXGenerateFocusEvent(winPtr, activeFlag);

    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * DoWindowActivate --







>
|
>







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519

int
GenerateActivateEvents(
    TkWindow *winPtr,
    int activeFlag)
{
    TkGenerateActivateEvents(winPtr, activeFlag);
    if (activeFlag || ![NSApp isActive]) {
	TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
    }
    return true;
}

/*
 *----------------------------------------------------------------------
 *
 * DoWindowActivate --
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
     */

    if (Tk_IsTopLevel(winPtr)) {
	wmPtr = winPtr->wmInfoPtr;
	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)))) {
	    if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {

		/*
		 * Don't set external width, since the user didn't change it







<







662
663
664
665
666
667
668

669
670
671
672
673
674
675
     */

    if (Tk_IsTopLevel(winPtr)) {
	wmPtr = winPtr->wmInfoPtr;
	if (flags & TK_LOCATION_CHANGED) {
	    wmPtr->x = x;
	    wmPtr->y = y;

	}
	if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
		((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
	    if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {

		/*
		 * Don't set external width, since the user didn't change it
Changes to macosx/tkMacOSXWm.c.
318
319
320
321
322
323
324

325
326
327
328
329
330
331
			    NSWindow *macWindow);
static void		GetMinSize(TkWindow *winPtr, int *minWidthPtr,
			    int *minHeightPtr);
static void		GetMaxSize(TkWindow *winPtr, int *maxWidthPtr,
			    int *maxHeightPtr);
static void		RemapWindows(TkWindow *winPtr,
			    MacDrawable *parentWin);


#pragma mark NSWindow(TKWm)

@implementation NSWindow(TKWm)

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- (NSPoint) tkConvertPointToScreen: (NSPoint) point







>







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
			    NSWindow *macWindow);
static void		GetMinSize(TkWindow *winPtr, int *minWidthPtr,
			    int *minHeightPtr);
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)

@implementation NSWindow(TKWm)

#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- (NSPoint) tkConvertPointToScreen: (NSPoint) point
677
678
679
680
681
682
683

684
685
686
687
688
689
690
    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
    wmPtr->hints.icon_mask = None;
    wmPtr->hints.window_group = None;
    wmPtr->leaderName = NULL;
    wmPtr->masterWindowName = NULL;
    wmPtr->icon = NULL;
    wmPtr->iconFor = NULL;

    wmPtr->sizeHintsFlags = 0;
    wmPtr->minWidth = wmPtr->minHeight = 1;
    wmPtr->maxWidth = 0;
    wmPtr->maxHeight = 0;
    wmPtr->gridWin = NULL;
    wmPtr->widthInc = wmPtr->heightInc = 1;
    wmPtr->minAspect.x = wmPtr->minAspect.y = 1;







>







678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
    wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0;
    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;
    wmPtr->maxHeight = 0;
    wmPtr->gridWin = NULL;
    wmPtr->widthInc = wmPtr->heightInc = 1;
    wmPtr->minAspect.x = wmPtr->minAspect.y = 1;
878
879
880
881
882
883
884

885
886
887
888







889
890
891
892
893
894
895
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;


    if (wmPtr == NULL) {
	return;
    }







    Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
	    TopLevelEventProc, winPtr);
    if (wmPtr->hints.flags & IconPixmapHint) {
	Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
    }
    if (wmPtr->hints.flags & IconMaskHint) {







>




>
>
>
>
>
>
>







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
 */

void
TkWmDeadWindow(
    TkWindow *winPtr)		/* Top-level window that's being deleted. */
{
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TkDisplay *dispPtr = TkGetDisplayList();

    if (wmPtr == NULL) {
	return;
    }
    
    /* 
     *If the dead window is a transient, remove it from the master's list.
     */

    RemoveTransient(winPtr);

    Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
    Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
	    TopLevelEventProc, winPtr);
    if (wmPtr->hints.flags & IconPixmapHint) {
	Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
    }
    if (wmPtr->hints.flags & IconMaskHint) {
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
























931
932
933
934
935
936
937
    if (wmPtr->iconFor != NULL) {
	wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
	wmPtr2->icon = NULL;
	wmPtr2->hints.flags &= ~IconWindowHint;
    }
    while (wmPtr->protPtr != NULL) {
	ProtocolHandler *protPtr = wmPtr->protPtr;

	wmPtr->protPtr = protPtr->nextPtr;
	Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
    }
    if (wmPtr->commandObj != NULL) {
	Tcl_DecrRefCount(wmPtr->commandObj);
    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    if (wmPtr->flags & WM_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
    }

























    /*
     * 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
     * own their portPtr's.
     */







<












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







921
922
923
924
925
926
927

928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
    if (wmPtr->iconFor != NULL) {
	wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
	wmPtr2->icon = NULL;
	wmPtr2->hints.flags &= ~IconWindowHint;
    }
    while (wmPtr->protPtr != NULL) {
	ProtocolHandler *protPtr = wmPtr->protPtr;

	wmPtr->protPtr = protPtr->nextPtr;
	Tcl_EventuallyFree(protPtr, TCL_DYNAMIC);
    }
    if (wmPtr->commandObj != NULL) {
	Tcl_DecrRefCount(wmPtr->commandObj);
    }
    if (wmPtr->clientMachine != NULL) {
	ckfree(wmPtr->clientMachine);
    }
    if (wmPtr->flags & WM_UPDATE_PENDING) {
	Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
    }

    /*
     * If the dead window has a transient, remove references to it from
     * the transient.
     */
    
    for (Transient *transientPtr = wmPtr->transientPtr;
    	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
    	TkWindow *winPtr2 = transientPtr->winPtr;
    	Window master = TkGetTransientMaster(winPtr2);
    	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
    	if (masterPtr == winPtr) {
    	    wmPtr2 = winPtr2->wmInfoPtr;
    	    wmPtr2->master = None;
    	    ckfree(wmPtr2->masterWindowName);
    	    wmPtr2->masterWindowName = NULL;
    	}
    }

    while (wmPtr->transientPtr != NULL) {
	Transient *transientPtr = wmPtr->transientPtr;
	wmPtr->transientPtr = transientPtr->nextPtr;
	ckfree(transientPtr);
    }

    /*
     * Delete the Mac window and remove it from the windowTable. The window
     * could be nil if the window was never mapped. However, we don't do this
     * for embedded windows, they don't go in the window list, and they do not
     * own their portPtr's.
     */
1754
1755
1756
1757
1758
1759
1760

1761
1762
1763
1764
1765
1766
1767
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (wmPtr->iconFor != NULL) {







>







1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    TkDisplay *dispPtr = TkGetDisplayList();

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (wmPtr->iconFor != NULL) {
1782
1783
1784
1785
1786
1787
1788





















1789
1790
1791
1792
1793
1794
1795
	    ZoomState : NormalState);
    [win setExcludedFromWindowsMenu:NO];
    TkMacOSXApplyWindowAttributes(winPtr, win);
    [win orderFront:nil];
    if (wmPtr->icon) {
	Tk_UnmapWindow((Tk_Window)wmPtr->icon);
    }





















    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmFocusmodelCmd --







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
	    ZoomState : NormalState);
    [win setExcludedFromWindowsMenu:NO];
    TkMacOSXApplyWindowAttributes(winPtr, win);
    [win orderFront:nil];
    if (wmPtr->icon) {
	Tk_UnmapWindow((Tk_Window)wmPtr->icon);
    }

    /*
     * If this window has a transient, the transient must also be deiconified if
     * it was withdrawn by the master.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
	Window master = TkGetTransientMaster(winPtr2);
	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
    	if (masterPtr == winPtr) {
	    if (!(wmPtr2->hints.initial_state == WithdrawnState &&
		  (transientPtr->flags & WITHDRAWN_BY_MASTER) == 0)) {
		TkpWmSetState(winPtr2, NormalState);
		transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
	    }
	}
    }
    
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmFocusmodelCmd --
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
WmIconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {







>







2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
WmIconifyCmd(
    Tk_Window tkwin,		/* Main window of the application. */
    TkWindow *winPtr,		/* Toplevel to work with */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    TkDisplay *dispPtr = TkGetDisplayList();
    register WmInfo *wmPtr = winPtr->wmInfoPtr;
    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2, objv, "window");
	return TCL_ERROR;
    }

    if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
2304
2305
2306
2307
2308
2309
2310


















2311
2312
2313
2314
2315
2316
2317
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, IconicState);
    if (wmPtr->icon) {
	Tk_MapWindow((Tk_Window)wmPtr->icon);
    }


















    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmIconmaskCmd --







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, IconicState);
    if (wmPtr->icon) {
	Tk_MapWindow((Tk_Window)wmPtr->icon);
    }

    /*
     * If this window has a transient the transient must be withdrawn when
     * the master is iconified.
     */

    for (Transient *transientPtr = wmPtr->transientPtr;
	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	Window master = TkGetTransientMaster(winPtr2);
	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
    	if (masterPtr == winPtr &&
	    winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
	    TkpWmSetState(winPtr2, WithdrawnState);
	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * WmIconmaskCmd --
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
	if (wmPtr->master != None) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj(wmPtr->masterWindowName, -1));
	}
	return TCL_OK;
    }
    if (Tcl_GetString(objv[3])[0] == '\0') {
	wmPtr->master = None;
	if (wmPtr->masterWindowName != NULL) {
	    ckfree(wmPtr->masterWindowName);
	}
	wmPtr->masterWindowName = NULL;
    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
	    return TCL_ERROR;
	}
	TkWindow* masterPtr = (TkWindow*) master;
	while (!Tk_TopWinHierarchy(masterPtr)) {

            /*
             * Ensure that the master window is actually a Tk toplevel.
             */

            masterPtr = masterPtr->parentPtr;







|
<
<
|
<




|







3593
3594
3595
3596
3597
3598
3599
3600


3601

3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
	if (wmPtr->master != None) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj(wmPtr->masterWindowName, -1));
	}
	return TCL_OK;
    }
    if (Tcl_GetString(objv[3])[0] == '\0') {
	RemoveTransient(winPtr);




    } else {
	if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
	    return TCL_ERROR;
	}
	TkWindow *masterPtr = (TkWindow*) master;
	while (!Tk_TopWinHierarchy(masterPtr)) {

            /*
             * Ensure that the master window is actually a Tk toplevel.
             */

            masterPtr = masterPtr->parentPtr;
3563
3564
3565
3566
3567
3568
3569





















3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582























































3583
3584
3585
3586
3587
3588
3589

	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;
	}






















	wmPtr->master = Tk_WindowId(masterPtr);
	masterWindowName = masterPtr->pathName;
	length = strlen(masterWindowName);
	if (wmPtr->masterWindowName != NULL) {
	    ckfree(wmPtr->masterWindowName);
	}
	wmPtr->masterWindowName = ckalloc(length+1);
	strcpy(wmPtr->masterWindowName, masterWindowName);
    }
    ApplyMasterOverrideChanges(winPtr, NULL);
    return TCL_OK;
}
























































/*
 *----------------------------------------------------------------------
 *
 * WmWithdrawCmd --
 *
 *	This procedure is invoked to process the "wm withdraw" Tcl command.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736

	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;
	}

	/*
	 * Add the transient to the master's list.
	 */

	Transient *transient = ckalloc(sizeof(Transient));
	transient->winPtr = winPtr;
	transient->flags = 0;
	transient->nextPtr = wmPtr->transientPtr;
	wmPtr2->transientPtr = transient;
	
	/*
	 * If the master is withdrawn or iconic then withdraw the transient.
	 */

	if ((wmPtr2->hints.initial_state == WithdrawnState ||
	     wmPtr2->hints.initial_state == IconicState) &&
	    wmPtr->hints.initial_state != WithdrawnState){
	    TkpWmSetState(winPtr, WithdrawnState);
	    transient->flags |= WITHDRAWN_BY_MASTER;
	}

	wmPtr->master = Tk_WindowId(masterPtr);
	masterWindowName = masterPtr->pathName;
	length = strlen(masterWindowName);
	if (wmPtr->masterWindowName != NULL) {
	    ckfree(wmPtr->masterWindowName);
	}
	wmPtr->masterWindowName = ckalloc(length+1);
	strcpy(wmPtr->masterWindowName, masterWindowName);
    }
    ApplyMasterOverrideChanges(winPtr, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * RemoveTransient --
 *
 *      Clears the transient's master record and removes the transient
 *      from the master's list.
 *
 * Results:
 *	None
 *
 * Side effects:
 *      References to a master are removed from the transient's wmInfo
 *	structure and references to the transient are removed from its
 *      master's wmInfo.
 *
 *----------------------------------------------------------------------
 */

static void
RemoveTransient(
    TkWindow *winPtr)
{
    WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
    TkDisplay *dispPtr = TkGetDisplayList();
    TkWindow *masterPtr;
    if (wmPtr == NULL || wmPtr->master == None) {
	return;
    }
    masterPtr = (TkWindow*)Tk_IdToWindow(dispPtr->display, wmPtr->master);
    wmPtr2 = masterPtr->wmInfoPtr;
    if (wmPtr2 == NULL) {
	return;
    }
    wmPtr->master = None;
    if (wmPtr->masterWindowName != NULL) {
	ckfree(wmPtr->masterWindowName);
    }
    wmPtr->masterWindowName = NULL;
    Transient *temp, *cursor = wmPtr2->transientPtr;
    if (cursor->winPtr == winPtr) {
	temp = cursor->nextPtr;
	ckfree(cursor);
	cursor = temp;
	masterPtr->wmInfoPtr->transientPtr = cursor;
    }
    while (cursor != NULL) {
	if (cursor->winPtr == winPtr) {
	    temp = cursor->nextPtr;
	    ckfree(cursor);
	    cursor = temp;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * WmWithdrawCmd --
 *
 *	This procedure is invoked to process the "wm withdraw" Tcl command.
3616
3617
3618
3619
3620
3621
3622

3623

3624

3625
3626















3627
3628
3629
3630
3631
3632
3633
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't withdraw %s: it is an icon for %s",
		Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	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];
















    return TCL_OK;
}

/*
 * Invoked by those wm subcommands that affect geometry.
 * Schedules a geometry update.







>

>

>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
    if (wmPtr->iconFor != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't withdraw %s: it is an icon for %s",
		Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
	Tcl_SetErrorCode(interp, "TK", "WM", "WITHDRAW", "ICON", NULL);
	return TCL_ERROR;
    }

    TkpWmSetState(winPtr, WithdrawnState);
    
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    TkDisplay *dispPtr = TkGetDisplayList();
    [win orderOut:nil];
    [win setExcludedFromWindowsMenu:YES];

    /*
     * If this window has a transient, the transient must also be withdrawn.
     */
    for (Transient *transientPtr = wmPtr->transientPtr;
	 transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
	TkWindow *winPtr2 = transientPtr->winPtr;
	Window master = TkGetTransientMaster(winPtr2);
	TkWindow *masterPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, master); 
    	if (masterPtr == winPtr &&
	    winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
	    TkpWmSetState(winPtr2, WithdrawnState);
	    transientPtr->flags |= WITHDRAWN_BY_MASTER;
	}
    }

    return TCL_OK;
}

/*
 * Invoked by those wm subcommands that affect geometry.
 * Schedules a geometry update.
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744

    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
    }
    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;
    }

    /*
     * If the window has already been mapped, must bring its geometry







<







4895
4896
4897
4898
4899
4900
4901

4902
4903
4904
4905
4906
4907
4908

    if (!(winPtr->flags & TK_TOP_LEVEL)) {
	Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window");
    }
    wmPtr->x = x;
    wmPtr->y = y;
    wmPtr->flags |= WM_MOVE_PENDING;

    if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {
	wmPtr->sizeHintsFlags |= USPosition;
	wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
    }

    /*
     * If the window has already been mapped, must bring its geometry
6217
6218
6219
6220
6221
6222
6223
6224
6225


6226
6227
6228
6229
6230
6231
6232
}

/*
 *----------------------------------------------------------------------
 *
 * TkpChangeFocus --
 *
 *	This procedure is a stub on the Mac because we always own the focus if
 *	we are a front most application.


 *
 * Results:
 *	The return value is the serial number of the command that changed the
 *	focus. It may be needed by the caller to filter out focus change
 *	events that were queued before the command. If the procedure doesn't
 *	actually change the focus then it returns 0.
 *







|
|
>
>







6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
}

/*
 *----------------------------------------------------------------------
 *
 * TkpChangeFocus --
 *
 *	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
 *	focus. It may be needed by the caller to filter out focus change
 *	events that were queued before the command. If the procedure doesn't
 *	actually change the focus then it returns 0.
 *
Changes to macosx/tkMacOSXWm.h.
32
33
34
35
36
37
38











39
40
41
42
43
44
45
    char* command;		/* Tcl command to invoke when a client message
				 * for this protocol arrives. The actual size
				 * of the structure varies to accommodate the
				 * needs of the actual command. THIS MUST BE
				 * THE LAST FIELD OF THE STRUCTURE. */
} ProtocolHandler;













/*
 * A data structure of the following type holds window-manager-related
 * information for each top-level window in an application.
 */

typedef struct TkWmInfo {







>
>
>
>
>
>
>
>
>
>
>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    char* command;		/* Tcl command to invoke when a client message
				 * for this protocol arrives. The actual size
				 * of the structure varies to accommodate the
				 * needs of the actual command. THIS MUST BE
				 * 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
 * information for each top-level window in an application.
 */

typedef struct TkWmInfo {
66
67
68
69
70
71
72



73
74
75
76
77
78
79
				 * "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. */




    /*
     * Information used to construct an XSizeHints structure for the window
     * manager:
     */

    int sizeHintsFlags;		/* Flags word for XSizeHints structure. If the







>
>
>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
				 * "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
     * manager:
     */

    int sizeHintsFlags;		/* Flags word for XSizeHints structure. If the
Changes to tests/menu.test.
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "On Windows, hit Escape to get this menu to go away"
    .m1 post
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 post x y"}
test menu-3.48 {MenuWidgetCmd procedure, "post" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 post foo 40
} -cleanup {
	destroy .m1







|







1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
	destroy .m1
} -body {
    menu .m1
    .m1 add command -label "On Windows, hit Escape to get this menu to go away"
    .m1 post
} -cleanup {
	destroy .m1
} -returnCodes error -result {wrong # args: should be ".m1 post x y ?index?"}
test menu-3.48 {MenuWidgetCmd procedure, "post" option} -setup {
	destroy .m1
} -body {
    menu .m1
    .m1 post foo 40
} -cleanup {
	destroy .m1
Changes to tests/menubut.test.
538
539
540
541
542
543
544




545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    menubutton .mb1
    rename .mb1 {}
    list [info command .mb*] [winfo children .]
} -cleanup {
    deleteWindows
} -result {{} {}}






test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 4 -highlightthickness 0
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result {38 23}
test menubutton-7.2 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 1 -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result {36 21}
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
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result {34 19}
test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -width 40 \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result {48 23}
test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -height 30 \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result {38 38}
test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result {25 35}
test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised -width 40 \
        -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result {46 33}
test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised -height 50 \
        -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result {23 56}
test menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {
    fonts
} -setup {
    deleteWindows
} -body {
    menubutton .mb -text String -bd 2 -relief raised -padx 0 -pady 0 \
        -highlightthickness 1







>
>
>
>
|












|






|





|






|





|













|













|









|









|









|







538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
    menubutton .mb1
    rename .mb1 {}
    list [info command .mb*] [winfo children .]
} -cleanup {
    deleteWindows
} -result {{} {}}

if {[tk windowingsystem] == "aqua"} {
    set extraWidth 36
} else {
    set extraWidth 0
}
test menubutton-7.1 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 4 -highlightthickness 0
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -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 3 -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -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 1 -highlightthickness 3 -padx 5 -pady 5
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {38 + $extraWidth}] 23]
test menubutton-7.4 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -width 40 \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {48 + $extraWidth}] 23]
test menubutton-7.5 {ComputeMenuButtonGeometry procedure} -constraints {
    testImageType
} -setup {
    deleteWindows
    image create test image1
} -body {
    menubutton .mb -image image1 -bd 2 -relief raised -height 30 \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
    imageCleanup
} -result [list [expr {38 + $extraWidth}] 38]
test menubutton-7.6 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised \
        -highlightthickness 2
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result [list [expr {25 + $extraWidth}] 35]
test menubutton-7.7 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised -width 40 \
        -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result [list [expr {46 + $extraWidth}] 33]
test menubutton-7.8 {ComputeMenuButtonGeometry procedure} -setup {
    deleteWindows
} -body {
    menubutton .mb -bitmap question -bd 2 -relief raised -height 50 \
        -highlightthickness 1
    pack .mb
    list [winfo reqwidth .mb] [winfo reqheight .mb]
} -cleanup {
    deleteWindows
} -result [list [expr {23 + $extraWidth}] 56]
test menubutton-7.9 {ComputeMenuButtonGeometry procedure} -constraints {
    fonts
} -setup {
    deleteWindows
} -body {
    menubutton .mb -text String -bd 2 -relief raised -padx 0 -pady 0 \
        -highlightthickness 1
Changes to tests/scale.test.
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184



































1185
1186
1187
1188
1189
1190
1191
} -result {untouched empty}


# Widget used in 14.* tests
destroy .s
pack [scale .s]
update
test scale-14.1 {RoundToResolution 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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .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 {
    .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 0 -digits 5
    update
    .s get 86 152
} -result {168.75}
destroy .s





































test scale-15.1 {ScaleVarProc procedure} -setup {
    deleteWindows
} -body {
    set y -130
    scale .s -from 0 -to -200 -variable y -orient horizontal -length 150







|





|






|





|






|





|






|





|






|





|






|





|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
} -result {untouched empty}


# Widget used in 14.* tests
destroy .s
pack [scale .s]
update
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 {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 {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 {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 {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 {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 {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 {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 {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 {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 {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 {RoundValueToResolution procedure} -body {
    .s configure -from 0 -to 225 -sliderlength 10 -length 114 -bd 2 \
        -orient horizontal -resolution 0 -digits 5
    update
    .s get 86 152
} -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
} -body {
    set y -130
    scale .s -from 0 -to -200 -variable y -orient horizontal -length 150
Changes to tests/send.test.
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
} "name2 {$commId name2\n}"
test send-7.4 {Tk_SetAppName procedure, name in use} {secureserver testsend} {
    tk appname name1
    testsend prop root InterpRegistry "$id foo\n$id foo #2\n$id foo #3\n"
    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} {
    setupbg
    set app [dobg {tk appname}]
    set a 66
    send -async $app [list send [tk appname] set a 77]
    set result $a
    after 200 set x 40
    tkwait variable x







>
|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
} "name2 {$commId name2\n}"
test send-7.4 {Tk_SetAppName procedure, name in use} {secureserver testsend} {
    tk appname name1
    testsend prop root InterpRegistry "$id foo\n$id foo #2\n$id foo #3\n"
    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}"

#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
    send -async $app [list send [tk appname] set a 77]
    set result $a
    after 200 set x 40
    tkwait variable x
218
219
220
221
222
223
224

225
226
227
228
229
230
231
232
233
234
235
    set a altDisplay
    tk appname xyzgorp
    list \[send xyzgorp set a\] \[send -displayof .t xyzgorp set a\]
    "]
    cleanupbg
    set result
} {altDisplay homeDisplay}

test send-8.3 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send -- -async foo bar baz} msg] $msg
} {1 {no application named "-async"}}
test send-8.4 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send -gorp foo bar baz} msg] $msg
} {1 {no application named "-gorp"}}
test send-8.5 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send -async foo} msg] $msg
} {1 {wrong # args: should be "send ?-option value ...? interpName arg ?arg ...?"}}
test send-8.6 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send foo} msg] $msg







>
|


|







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    set a altDisplay
    tk appname xyzgorp
    list \[send xyzgorp set a\] \[send -displayof .t xyzgorp set a\]
    "]
    cleanupbg
    set result
} {altDisplay homeDisplay}
# 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 notAqua} {
    list [catch {send -gorp foo bar baz} msg] $msg
} {1 {no application named "-gorp"}}
test send-8.5 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send -async foo} msg] $msg
} {1 {wrong # args: should be "send ?-option value ...? interpName arg ?arg ...?"}}
test send-8.6 {Tk_SendCmd procedure, options} {secureserver} {
    list [catch {send foo} msg] $msg
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    string tolower [list [catch {send [tk appname] open bad_file} msg] \
	    $msg $errorInfo $errorCode]
} {1 {couldn't open "bad_file": no such file or directory} {couldn't open "bad_file": no such file or directory
    while executing
"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} {
    list [catch {send bogus_name bogus_command} msg] $msg
} {1 {no application named "bogus_name"}}

catch {
    newApp "" t_s_1 Test
    t_s_1 eval wm withdraw .
}







|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    string tolower [list [catch {send [tk appname] open bad_file} msg] \
	    $msg $errorInfo $errorCode]
} {1 {couldn't open "bad_file": no such file or directory} {couldn't open "bad_file": no such file or directory
    while executing
"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 notAqua} {
    list [catch {send bogus_name bogus_command} msg] $msg
} {1 {no application named "bogus_name"}}

catch {
    newApp "" t_s_1 Test
    t_s_1 eval wm withdraw .
}
538
539
540
541
542
543
544

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
test send-12.1 {TimeoutProc procedure} {secureserver testsend} {
    testsend prop root InterpRegistry "$id dummy\n"
    list [catch {send dummy foo} msg] $msg
} {1 {target application died or uses a Tk version before 4.0}}

catch {testsend prop root InterpRegistry ""}


test send-12.2 {TimeoutProc procedure} {secureserver} {
    winfo interps
    tk appname tktest
    update
    setupbg
    set app [dobg {
	after 10 {after 10 {after 5000; exit}}
	tk appname
    }]
    after 200
    set result [list [catch {send $app foo} msg] $msg]
    cleanupbg
    set result
} {1 {target application died}}


winfo interps
tk appname tktest
test send-13.1 {DeleteProc procedure} {secureserver} {
    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} {
    winfo interps
    tk appname tktest
    rename send {}
    set result {}
    lappend result [winfo interps] [info commands send]
    tk appname foo
    lappend result [winfo interps] [info commands send]







>
|














>


|






|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
test send-12.1 {TimeoutProc procedure} {secureserver testsend} {
    testsend prop root InterpRegistry "$id dummy\n"
    list [catch {send dummy foo} msg] $msg
} {1 {target application died or uses a Tk version before 4.0}}

catch {testsend prop root InterpRegistry ""}

#macOS does not send to other processes
test send-12.2 {TimeoutProc procedure} {secureserver notAqua} {
    winfo interps
    tk appname tktest
    update
    setupbg
    set app [dobg {
	after 10 {after 10 {after 5000; exit}}
	tk appname
    }]
    after 200
    set result [list [catch {send $app foo} msg] $msg]
    cleanupbg
    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 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 notAqua} {
    winfo interps
    tk appname tktest
    rename send {}
    set result {}
    lappend result [winfo interps] [info commands send]
    tk appname foo
    lappend result [winfo interps] [info commands send]
Changes to tests/text.test.
3798
3799
3800
3801
3802
3803
3804






3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821

3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
} -cleanup {
    destroy .top
} -result {150x140+}
# This test was failing 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.






test text-14.19 {ConfigureText procedure} -setup {
    toplevel .top
    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
} -body {
    .top.t configure -width 20 -height 10 -setgrid 1
    wm overrideredirect .top 1
    pack .top.t
    wm geometry .top +0+0
    update
    wm geometry .top
} -cleanup {
    destroy .top
} -result {20x10+0+0}
# 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.

test text-14.20 {ConfigureText procedure} -setup {
    toplevel .top
    text .top.t -font {Courier -12} -borderwidth 2 -highlightthickness 2
} -body {
    .top.t configure -width 20 -height 10 -setgrid 1
    wm overrideredirect .top 1
    pack .top.t
    wm geometry .top +0+0
    update
    set result [wm geometry .top]
    wm geometry .top 15x8
    update
    lappend result [wm geometry .top]
    .top.t configure -wrap word
    update
    lappend result [wm geometry .top]
} -cleanup {
    destroy .top
} -result {20x10+0+0 15x8+0+0 15x8+0+0}


test text-15.1 {TextWorldChanged procedure, spacing options} -constraints {
    fonts
} -body {
    text .t -width 20 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2
    set result [winfo reqheight .t]







>
>
>
>
>
>







|




|




>







|










|







3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
} -cleanup {
    destroy .top
} -result {150x140+}
# This test was failing 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, 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
} -body {
    .top.t configure -width 20 -height 10 -setgrid 1
    wm overrideredirect .top 1
    pack .top.t
    wm geometry .top +0+$minY
    update
    wm geometry .top
} -cleanup {
    destroy .top
} -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
} -body {
    .top.t configure -width 20 -height 10 -setgrid 1
    wm overrideredirect .top 1
    pack .top.t
    wm geometry .top +0+$minY
    update
    set result [wm geometry .top]
    wm geometry .top 15x8
    update
    lappend result [wm geometry .top]
    .top.t configure -wrap word
    update
    lappend result [wm geometry .top]
} -cleanup {
    destroy .top
} -result "20x10+0+$minY 15x8+0+$minY 15x8+0+$minY"


test text-15.1 {TextWorldChanged procedure, spacing options} -constraints {
    fonts
} -body {
    text .t -width 20 -height 10 -font {Courier -12} -borderwidth 2 -highlightthickness 2
    set result [winfo reqheight .t]
Changes to tests/unixEmbed.test.
1
2
3
4
5
6
7
8
9
10
11
12































13
14
15
16
17
18
19
# 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.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
eval tcltest::configure $argv
tcltest::loadTestedCommands
namespace import -force tcltest::test
































setupbg
dobg {wm withdraw .}

# eatColors --
# Creates a toplevel window and allocates enough colors in it to
# use up all the slots in the colormap.












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 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.
#
# Copyright (c) 1996-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.

package require tcltest 2.2
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 .}

# eatColors --
# Creates a toplevel window and allocates enough colors in it to
# use up all the slots in the colormap.
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115





















116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133























134
135
136
137
138
139
140
    toplevel .x -use [winfo id .t]
    colorsFree .x
} -cleanup {
	deleteWindows
} -result {1}

test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    dobg "set w [winfo id .f1]"
    dobg {
	eval destroy [winfo child .]
	toplevel .t -use $w
	list [testembed] [expr [lindex [lindex [testembed all] 0] 0] - $w]
    }
} -cleanup {
	deleteWindows
} -result {{{XXX {} {} .t}} 0}





















test unixEmbed-1.6 {TkpUseWindow procedure, creating Container records} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    dobg "set w1 [winfo id .f1]"
    dobg "set w2 [winfo id .f2]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    toplevel .t2 -use $w2
	    testembed
    }
} -cleanup {
	deleteWindows























} -result {{XXX {} {} .t2} {XXX {} {} .t1}}
test unixEmbed-1.7 {TkpUseWindow procedure, container and embedded in same app} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50







|















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    toplevel .x -use [winfo id .t]
    colorsFree .x
} -cleanup {
	deleteWindows
} -result {1}

test unixEmbed-1.5 {TkpUseWindow procedure, creating Container records} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    dobg "set w [winfo id .f1]"
    dobg {
	eval destroy [winfo child .]
	toplevel .t -use $w
	list [testembed] [expr [lindex [lindex [testembed all] 0] 0] - $w]
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -container 1 -width 200 -height 50
    pack .f1 .f2
    dobg "set w1 [winfo id .f1]"
    dobg "set w2 [winfo id .f2]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    toplevel .t2 -use $w2
	    testembed
    }
} -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 {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
























175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192






















193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238





















239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274























275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293























294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314






















315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

























338
339
340
341
342
343
344
345
346
} -result {{XXX .f2 {} .t2} {XXX .f1 {} .t1}}

# Can't think of any way to test the procedures TkpMakeWindow,
# TkpMakeContainer, or EmbedErrorProc.


test unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    testembed
    }
    destroy .f1
    update
    dobg {
	    testembed
    }
} -cleanup {
	deleteWindows
} -result {}
























test unixEmbed-2.2 {EmbeddedEventProc procedure} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    testembed
	    destroy .t1
	    testembed
    }
} -cleanup {
	deleteWindows
} -result {}






















test unixEmbed-2.3 {EmbeddedEventProc procedure} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    toplevel .t1 -use [winfo id .f1]
    update
    destroy .f1
    testembed
} -result {}
test unixEmbed-2.4 {EmbeddedEventProc procedure} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    toplevel .t1 -use [winfo id .f1]

    update
    destroy .t1
    set x [testembed]
    update
    list $x [testembed]
} -cleanup {
	deleteWindows
} -result {{{XXX .f1 {} {}}} {}}


test unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints {
    unix testembed nonPortable
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    set x [testembed]
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    wm withdraw .t1
    }
    list $x [testembed]
} -cleanup {
	deleteWindows
} -result {{{XXX .f1 {} {}}} {{XXX .f1 XXX {}}}}





















test unixEmbed-3.2 {ContainerEventProc procedure, set size on creation} -constraints {
	unix
} -setup {
	deleteWindows

} -body {
    toplevel .t1 -container 1
    wm geometry .t1 +0+0
    toplevel .t2 -use [winfo id .t1] -bg red
    update
    wm geometry .t2
} -cleanup {
	deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1 -bd 2 -relief raised
	    update
	    wm geometry .t1 +30+40
    }
    update
    dobg {
	    wm geometry .t1
    }
} -cleanup {
	deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.4 {ContainerEventProc procedure, disallow position changes} -constraints {
	unix























} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    update
	    wm geometry .t1 300x100+30+40
    }
    update
    dobg {
	    wm geometry .t1
    }
} -cleanup {
	deleteWindows
} -result {300x100+0+0}























test unixEmbed-3.5 {ContainerEventProc procedure, geometry requests} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    dobg {
	    .t1 configure -width 300 -height 80
    }
    update
    list [winfo width .f1] [winfo height .f1] [dobg {wm geometry .t1}]
} -cleanup {
	deleteWindows
} -result {300 80 300x80+0+0}






















test unixEmbed-3.6 {ContainerEventProc procedure, map requests} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    set x unmapped
	    bind .t1 <Map> {set x mapped}
    }
    update
    dobg {
	    after 100
	    update
	    set x
    }
} -cleanup {
	deleteWindows
} -result {mapped}

























test unixEmbed-3.7 {ContainerEventProc procedure, destroy events} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    bind .f1 <Destroy> {set x dead}







|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|















|
<

>


<

|


|



|














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>










|



















|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|





















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

332
333
334
335

336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
} -result {{XXX .f2 {} .t2} {XXX .f1 {} .t1}}

# Can't think of any way to test the procedures TkpMakeWindow,
# TkpMakeContainer, or EmbedErrorProc.


test unixEmbed-2.1 {EmbeddedEventProc procedure} -constraints {
	unix testembed notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    testembed
    }
    destroy .f1
    update
    dobg {
	    testembed
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    testembed
	    destroy .t1
	    testembed
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    toplevel .t1 -use [winfo id .f1]
    update
    destroy .f1
    testembed
} -result {}
test unixEmbed-2.4 {EmbeddedEventProc procedure} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    pack [frame .f1 -container 1 -width 200 -height 50]

    toplevel .t1 -use [winfo id .f1]
    set x [testembed]
    update
    destroy .t1

    update
    list $x [winfo exists .t1] [winfo exists .f1] [testembed]
} -cleanup {
	deleteWindows
} -result "{{XXX .f1 {} .t1}} 0 0 {}"


test unixEmbed-3.1 {ContainerEventProc procedure, detect creation} -constraints {
    unix testembed notPortable
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    set x [testembed]
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    wm withdraw .t1
    }
    list $x [testembed]
} -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
} -setup {
	deleteWindows
    update
} -body {
    toplevel .t1 -container 1
    wm geometry .t1 +0+0
    toplevel .t2 -use [winfo id .t1] -bg red
    update
    wm geometry .t2
} -cleanup {
	deleteWindows
} -result {200x200+0+0}
test unixEmbed-3.3 {ContainerEventProc procedure, disallow position changes} -constraints {
	unix notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1 -bd 2 -relief raised
	    update
	    wm geometry .t1 +30+40
    }
    update
    dobg {
	    wm geometry .t1
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    update
	    wm geometry .t1 300x100+30+40
    }
    update
    dobg {
	    wm geometry .t1
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    dobg {
	    .t1 configure -width 300 -height 80
    }
    update
    list [winfo width .f1] [winfo height .f1] [dobg {wm geometry .t1}]
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    set x unmapped
	    bind .t1 <Map> {set x mapped}
    }
    update
    dobg {
	    after 100
	    update
	    set x
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    bind .f1 <Destroy> {set x dead}
354
355
356
357
358
359
360


















361






362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385























386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404















405







406

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427


























428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
























450
451
452
453
454
455
456
457
458
	    destroy .t1
    }
    update
    list $x [winfo exists .f1]
} -cleanup {
	deleteWindows
} -result {dead 0}


























test unixEmbed-4.1 {EmbedStructureProc procedure, configure events} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    dobg {
	    .t1 configure -width 180 -height 100
    }
    update
    dobg {
	    winfo geometry .t1
    }
} -cleanup {
	deleteWindows
} -result {180x100+0+0}























test unixEmbed-4.2 {EmbedStructureProc procedure, destroy events} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    set x [testembed]
    destroy .f1

    list $x [testembed]
} -cleanup {
	deleteWindows
} -result {{{XXX .f1 XXX {}}} {}}

























test unixEmbed-5.1 {EmbedFocusProc procedure, FocusIn events} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    bind .t1 <FocusIn> {lappend x "focus in %W"}
	    bind .t1 <FocusOut> {lappend x "focus out %W"}
	    set x {}
    }
    focus -force .f1
    update
    dobg {set x}
} -cleanup {
	deleteWindows
} -result {{focus in .t1}}


























test unixEmbed-5.2 {EmbedFocusProc procedure, focusing on dead window} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	eval destroy [winfo child .]
	toplevel .t1 -use $w1
    }
    update
    dobg {
	    after 200 {destroy .t1}
    }
    after 400
    focus -force .f1
    update
} -cleanup {
	deleteWindows
} -result {}
























test unixEmbed-5.3 {EmbedFocusProc procedure, FocusOut events} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>


|





















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|













>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>

|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
	    destroy .t1
    }
    update
    list $x [winfo exists .f1]
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    dobg {
	    .t1 configure -width 180 -height 100
    }
    update
    dobg {
	    winfo geometry .t1
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
	    bind .t1 <FocusIn> {lappend x "focus in %W"}
	    bind .t1 <FocusOut> {lappend x "focus out %W"}
	    set x {}
    }
    focus -force .f1
    update
    dobg {set x}
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	eval destroy [winfo child .]
	toplevel .t1 -use $w1
    }
    update
    dobg {
	    after 200 {destroy .t1}
    }
    after 400
    focus -force .f1
    update
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
467
468
469
470
471
472
473


















474










475

476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500

























501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522





















523


524

525

526
527
528
529
530
531
532
533
534
535
    set x [dobg {update; set x}]
    focus .
    update
    list $x [dobg {update; set x}]
} -cleanup {
	deleteWindows
} -result {{{focus in .t1}} {{focus in .t1} {focus out .t1}}}































test unixEmbed-6.1 {EmbedGeometryRequest procedure, window changes size} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    update
    dobg {
	    bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
	    set x {}
	    .t1 configure -width 300 -height 120
	    update
	    list $x [winfo geom .t1]
    }
} -cleanup {
	deleteWindows
} -result {{{configure .t1 300 120}} 300x120+0+0}
test unixEmbed-6.2 {EmbedGeometryRequest procedure, window changes size} -constraints {
	unix

























} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    place .f1 -width 200 -height 200
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1
    }
    after 300 {set x done}
    vwait x
    dobg {
	    bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
	    set x {}
	    .t1 configure -width 300 -height 120
	    update
	    list $x [winfo geom .t1]
    }
} -cleanup {
	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
} -setup {
	deleteWindows
} -body {
    deleteWindows
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>

>

|









<
|
<









|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<
<
|
<



|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>

>


|







823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871

872

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917


918

919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
    set x [dobg {update; set x}]
    focus .
    update
    list $x [dobg {update; set x}]
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1

            update

	    bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
	    set x {}
	    .t1 configure -width 300 -height 120
	    update
	    list $x [winfo geom .t1]
    }
} -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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    place .f1 -width 200 -height 200
    dobg "set w1 [winfo id .f1]"
    dobg {
	    eval destroy [winfo child .]
	    toplevel .t1 -use $w1


            update

	    bind .t1 <Configure> {lappend x {configure .t1 %w %h}}
	    set x {}
	    .t1 configure -width 300 -height 120
            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 notAqua
} -setup {
	deleteWindows
} -body {
    deleteWindows
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
547
548
549
550
551
552
553
554
555

































556
557
558
559
560
561
562
563
564
	    event generate .t1 <KeyPress> -keysym a
	    set y
    }]
    update
    list $x $y
} -cleanup {
	deleteWindows
    bind . <KeyPress> {}
} -result {{{key a 1}} {}}

































test unixEmbed-7.2 {TkpRedirectKeyEvent procedure, don't forward keystroke width} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
	    event generate .t1 <KeyPress> -keysym a
	    set y
    }]
    update
    list $x $y
} -cleanup {
	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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1
    dobg "set w1 [winfo id .f1]"
    dobg {
579
580
581
582
583
584
585














586



















587
588


589
590
591
592
593
594
595
    }]
    update
    list $x $y
} -cleanup {
	deleteWindows
    bind . <KeyPress> {}
} -result {{} {{key b}}}



































test unixEmbed-8.1 {TkpClaimFocus procedure} -constraints unix -setup {


	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -width 200 -height 50
    pack .f1 .f2
    dobg "set w1 [winfo id .f1]"
    dobg {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>







1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
    }]
    update
    list $x $y
} -cleanup {
	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 notAqua
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -width 200 -height 50
    pack .f1 .f2
    dobg "set w1 [winfo id .f1]"
    dobg {
604
605
606
607
608
609
610
611
612
613
614























615





616
617
618
619
620

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
	    update
	    after 500
	    update
	    lappend x [focus]
    }] [focus]
} -cleanup {
	deleteWindows
} -result {{{} .t1} .f1}
test unixEmbed-8.2 {TkpClaimFocus procedure} -constraints unix -setup {
	deleteWindows
    catch {interp delete child}























    deleteWindows





} -body {
    frame .f1 -container 1 -width 200 -height 50
    frame .f2 -width 200 -height 50
    pack .f1 .f2
    interp create child

    child eval "set argv {-use [winfo id .f1]}"
    load {} Tk child
    child eval {
	    . configure -bd 2 -highlightthickness 2 -relief sunken
    }
    focus -force .f2
    update
    list [child eval {
	    focus .
	    set x [list [focus]]
	    update
	    lappend x [focus]
    }] [focus]
} -cleanup {
	deleteWindows
} -result {{{} .} .f1}
catch {interp delete child}


test unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50








|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>




|
>

















<







1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168
1169
1170
1171
	    update
	    after 500
	    update
	    lappend x [focus]
    }] [focus]
} -cleanup {
	deleteWindows
} -result {{{} .t1} .f1}
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 {
	    . configure -bd 2 -highlightthickness 2 -relief sunken
    }
    focus -force .f2
    update
    list [child eval {
	    focus .
	    set x [list [focus]]
	    update
	    lappend x [focus]
    }] [focus]
} -cleanup {
	deleteWindows
} -result {{{} .} .f1}
catch {interp delete child}


test unixEmbed-9.1 {EmbedWindowDeleted procedure, check parentPtr} -constraints {
	unix testembed
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678























679
680
681
682
683
684
685
686
687

688
689
690
691
692
693
694
	    lappend x [testembed]
    }
    set x
} -cleanup {
	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
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1

    dobg "set w1 [winfo id .f1]"
    dobg {
	    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 {
	deleteWindows
} -result {{{XXX {} {} .t1}} {}}

























test unixEmbed-10.1 {geometry propagation in tkUnixWm.c/UpdateGeometryInfo} -constraints {
	unix
} -setup {
	deleteWindows
} -body {
    frame .f1 -container 1 -width 200 -height 50
    pack .f1

    toplevel .t1 -use [winfo id .f1] -width 150 -height 80
    update
    wm geometry .t1 +40+50
    update
    wm geometry .t1
} -cleanup {
	deleteWindows







|





>












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>







1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
	    lappend x [testembed]
    }
    set x
} -cleanup {
	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 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 .]
	    toplevel .t1 -use $w1 -highlightthickness 2 -bd 2 -relief sunken
	    set x {}
	    lappend x [testembed]
	    destroy .t1
	    lappend x [testembed]
    }
} -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
} -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
    update
    wm geometry .t1
} -cleanup {
	deleteWindows
710
711
712
713
714
715
716
717
} -result {70x300+0+0}

# cleanup
deleteWindows
cleanupbg
cleanupTests
return








<
1261
1262
1263
1264
1265
1266
1267

} -result {70x300+0+0}

# cleanup
deleteWindows
cleanupbg
cleanupTests
return

Changes to tests/unixWm.test.
35
36
37
38
39
40
41
42















43
44
45
46
47
48
49
50
51
    deleteWindows
    foreach i {.raise1 .raise2 .raise3} {
	toplevel $i
	wm geom $i 150x100+0+0
	update
    }
}
















set i 1
foreach geom {+20+80 +80+20 +0+0} {
    destroy .t
    test unixWm-1.$i {initial window position} unix {
	toplevel .t -width 200 -height 150
	wm geom .t $geom
	update
	wm geom .t
    } 200x150$geom








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    deleteWindows
    foreach i {.raise1 .raise2 .raise3} {
	toplevel $i
	wm geom $i 150x100+0+0
	update
    }
}

# 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 "+23+80 +80+23 +0+$Y0" {
    destroy .t
    test unixWm-1.$i {initial window position} unix {
	toplevel .t -width 200 -height 150
	wm geom .t $geom
	update
	wm geom .t
    } 200x150$geom
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
wm geom .t +200+200
update
wm geom .t +150+150
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} {
    test unixWm-2.$i {moving window while mapped} unix {
	wm geom .t $geom
	update
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
    test unixWm-3.$i {moving window while iconified} unix {
	wm iconify .t
	sleep 200
	wm geom .t $geom
	update
	wm deiconify .t
	animationDelay
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
foreach geom {+20+80 +100+40 +0+0} {
    test unixWm-4.$i {moving window while withdrawn} unix {
	wm withdraw .t
	sleep 200
	wm geom .t $geom
	update
	wm deiconify .t
	animationDelay







|











|















|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
wm geom .t +200+200
update
wm geom .t +150+150
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+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
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
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
	wm geom .t $geom
	update
	wm deiconify .t
	animationDelay
	scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
	format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
		[eval expr $y$ysign$yerr]
    } $geom
    incr i
}

set i 1
foreach geom "+20+80 +100+40 +0+$Y0" {
    test unixWm-4.$i {moving window while withdrawn} unix {
	wm withdraw .t
	sleep 200
	wm geom .t $geom
	update
	wm deiconify .t
	animationDelay
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    wm withdraw .t
    wm iconify .t
    list [winfo ismapped .t] [wm state .t]
} {0 iconic}

destroy .t
toplevel .t -width 200 -height 100
wm geom .t +10+10
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
test unixWm-6.2 {size changes} unix {
    wm geom .t 250x60
    .t config -width 170 -height 140
    update
    wm geom .t
} 250x60+10+10
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
test unixWm-6.4 {size changes} {unix nonPortable userInteraction} {
    wm minsize .t 1 1
    update
    puts stdout "Please resize window \"t\" with the mouse (but don't move it!),"
    puts -nonewline stdout "then hit return: "
    flush stdout
    gets stdin







|






|





|






|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
    wm withdraw .t
    wm iconify .t
    list [winfo ismapped .t] [wm state .t]
} {0 iconic}

destroy .t
toplevel .t -width 200 -height 100
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+23
test unixWm-6.2 {size changes} unix {
    wm geom .t 250x60
    .t config -width 170 -height 140
    update
    wm geom .t
} 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+23
test unixWm-6.4 {size changes} {unix nonPortable userInteraction} {
    wm minsize .t 1 1
    update
    puts stdout "Please resize window \"t\" with the mouse (but don't move it!),"
    puts -nonewline stdout "then hit return: "
    flush stdout
    gets stdin
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
    pack .t.l -fill both -expand 1
    update
    wm geometry .t
} {30x10+0+0}
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
    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}

test unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {
    destroy .t
    toplevel .t -width 400 -height 150
    wm geometry .t +0+0
    tkwait visibility .t
    set result {}







|






|







1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
    pack .t.l -fill both -expand 1
    update
    wm geometry .t
} {30x10+0+0}
test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix {
    destroy .t
    toplevel .t
    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+$Y0"

test unixWm-41.1 {ConfigureEvent procedure, internally generated size changes} unix {
    destroy .t
    toplevel .t -width 400 -height 150
    wm geometry .t +0+0
    tkwait visibility .t
    set result {}
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
} [list 5 [expr [winfo screenheight .t] - 70]]
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
    tkwait visibility .t
    wm overrideredirect .t 1
    update
    wm geometry .t -30+2
    update
    list [winfo x .t] [winfo y .t]
} [list [expr [winfo screenwidth .t] - 110] 2]
destroy .t

test unixWm-44.9 {UpdateGeometryInfo procedure, updating fixed dimensions} {unix testwrapper} {
    destroy .t
    toplevel .t -width 80 -height 60
    wm resizable .t 0 0
    wm geometry .t +0+0







|


|







1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
} [list 5 [expr [winfo screenheight .t] - 70]]
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
    tkwait visibility .t
    wm overrideredirect .t 1
    update
    wm geometry .t -30+$Y2
    update
    list [winfo x .t] [winfo y .t]
} [list [expr [winfo screenwidth .t] - 110] $Y2]
destroy .t

test unixWm-44.9 {UpdateGeometryInfo procedure, updating fixed dimensions} {unix testwrapper} {
    destroy .t
    toplevel .t -width 80 -height 60
    wm resizable .t 0 0
    wm geometry .t +0+0
Changes to unix/tkUnixEmbed.c.
499
500
501
502
503
504
505







506

507
508
509
510
511
512
513
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;
    Tk_ErrorHandler errHandler;

    if (eventPtr->type == ConfigureNotify) {







	if (containerPtr->wrapper != None) {

	    /*
	     * Ignore errors, since the embedded application could have
	     * deleted its window.
	     */

	    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
		    -1, -1, NULL, NULL);







>
>
>
>
>
>
>

>







499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = clientData;
    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.
	     */

	    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
		    -1, -1, NULL, NULL);
869
870
871
872
873
874
875

876
877
878
879
880
881
882
883
884
885
886









887

888
889
890
891
892
893
894
895

896

897
898
899
900
901

902
903
904
905
906
907
908
909

910

911
912
913
914
915
916
917
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    Container *containerPtr;
    Tcl_DString dString;
    char buffer[50];

    ThreadSpecificData *tsdPtr =
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
	all = 1;
    } else {
	all = 0;
    }
    Tcl_DStringInit(&dString);
    for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL;
	    containerPtr = containerPtr->nextPtr) {









	Tcl_DStringStartSublist(&dString);

	if (containerPtr->parent == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}

	if (containerPtr->parentPtr == NULL) {

	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->parentPtr->pathName);
	}

	if (containerPtr->wrapper == None) {
	    Tcl_DStringAppendElement(&dString, "");
	} else if (all) {
	    sprintf(buffer, "0x%" TCL_Z_MODIFIER "x", (size_t) containerPtr->wrapper);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}

	if (containerPtr->embeddedPtr == NULL) {

	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->embeddedPtr->pathName);
	}
	Tcl_DStringEndSublist(&dString);
    }







>











>
>
>
>
>
>
>
>
>

>








>
|
>





>








>
|
>







877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])		/* Argument strings. */
{
    int all;
    Container *containerPtr;
    Tcl_DString dString;
    char buffer[50];
    Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
    ThreadSpecificData *tsdPtr =
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
	all = 1;
    } else {
	all = 0;
    }
    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%" TCL_Z_MODIFIER "x", (size_t) containerPtr->parent);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	/* 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%" TCL_Z_MODIFIER "x", (size_t) containerPtr->wrapper);
	    Tcl_DStringAppendElement(&dString, buffer);
	} else {
	    Tcl_DStringAppendElement(&dString, "XXX");
	}
	/* Embedded window pathName */
	if (containerPtr->embeddedPtr == NULL ||
	    embeddedInterp != interp) {
	    Tcl_DStringAppendElement(&dString, "");
	} else {
	    Tcl_DStringAppendElement(&dString,
		    containerPtr->embeddedPtr->pathName);
	}
	Tcl_DStringEndSublist(&dString);
    }
Changes to unix/tkUnixMenu.c.
884
885
886
887
888
889
890
891



892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908































































































909
910
911
912
913
914
915
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	Posts a menu on the screen



 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    int x, int y)
{
    return TkPostTearoffMenu(interp, menuPtr, x, y);































































































}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuSeparatorGeometry --
 *







|
>
>
>














|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	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.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    int x, int y, int index)
{
    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;
}

/*
 *----------------------------------------------------------------------
 *
 * GetMenuSeparatorGeometry --
 *
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
    windowWidth = x + indicatorSpace + labelWidth + accelWidth
	    + 2 * activeBorderWidth + borderWidth;

    windowHeight += borderWidth;

    /*
     * The X server doesn't like zero dimensions, so round up to at least 1 (a
     * zero-sized menu should never really occur, anyway).
     */








<







1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824
1825
1826
1827
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
    windowWidth = x + indicatorSpace + labelWidth + accelWidth
	    + 2 * activeBorderWidth + borderWidth;

    windowHeight += borderWidth;

    /*
     * The X server doesn't like zero dimensions, so round up to at least 1 (a
     * zero-sized menu should never really occur, anyway).
     */

Changes to unix/tkUnixScale.c.
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
		    / (double) scalePtr->fontHeight;
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		    tickValue += tickInterval) {
		/*
		 * The TkRoundToResolution call gets rid of accumulated
		 * round-off errors, if any.
		 */

		tickValue = TkRoundToResolution(scalePtr, tickValue);
		if (scalePtr->toValue >= scalePtr->fromValue) {
		    if (tickValue > scalePtr->toValue) {
			break;
		    }
		} else {
		    if (tickValue < scalePtr->toValue) {
			break;







|



|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
		    / (double) scalePtr->fontHeight;
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		    tickValue += tickInterval) {
		/*
		 * The TkRoundValueToResolution call gets rid of accumulated
		 * round-off errors, if any.
		 */

		tickValue = TkRoundValueToResolution(scalePtr, tickValue);
		if (scalePtr->toValue >= scalePtr->fromValue) {
		    if (tickValue > scalePtr->toValue) {
			break;
		    }
		} else {
		    if (tickValue < scalePtr->toValue) {
			break;
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
		    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		 tickValue += tickInterval) {
		/*
		 * The TkRoundToResolution call gets rid of accumulated
		 * round-off errors, if any.
		 */

		tickValue = TkRoundToResolution(scalePtr, tickValue);
		if (scalePtr->toValue >= scalePtr->fromValue) {
		    if (tickValue > scalePtr->toValue) {
			break;
		    }
		} else {
		    if (tickValue < scalePtr->toValue) {
			break;







|



|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
		    / (double) Tk_TextWidth(scalePtr->tkfont, valueString, -1);
	    if (ticks > maxTicks) {
		tickInterval *= (ticks / maxTicks);
	    }
	    for (tickValue = scalePtr->fromValue; ;
		 tickValue += tickInterval) {
		/*
		 * The TkRoundValueToResolution call gets rid of accumulated
		 * round-off errors, if any.
		 */

		tickValue = TkRoundValueToResolution(scalePtr, tickValue);
		if (scalePtr->toValue >= scalePtr->fromValue) {
		    if (tickValue > scalePtr->toValue) {
			break;
		    }
		} else {
		    if (tickValue < scalePtr->toValue) {
			break;
Changes to win/tkWinEmbed.c.
852
853
854
855
856
857
858









859
860
861
862
863
864
865
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = (Container *)clientData;
    Tk_Window tkwin = (Tk_Window)containerPtr->parentPtr;

    if (eventPtr->type == ConfigureNotify) {









	/*
	 * Resize the embedded window, if there is any.
	 */

	if (containerPtr->embeddedHWnd) {
	    SetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,
		    Tk_Width(tkwin), Tk_Height(tkwin), SWP_NOZORDER);







>
>
>
>
>
>
>
>
>







852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
    ClientData clientData,	/* Token for container window. */
    XEvent *eventPtr)		/* ResizeRequest event. */
{
    Container *containerPtr = (Container *)clientData;
    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.
	 */

	if (containerPtr->embeddedHWnd) {
	    SetWindowPos(containerPtr->embeddedHWnd, NULL, 0, 0,
		    Tk_Width(tkwin), Tk_Height(tkwin), SWP_NOZORDER);
Changes to win/tkWinMenu.c.
739
740
741
742
743
744
745
746



747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780







781
782
783
784
785
786
787
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	Posts a menu on the screen



 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    int x, int y)
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    int result, flags;
    RECT noGoawayRect;
    POINT point;
    Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
    int oldServiceMode = Tcl_GetServiceMode();
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->inPostMenu++;

    CallPendingReconfigureImmediately(menuPtr);

    result = TkPreprocessMenu(menuPtr);
    if (result != TCL_OK) {
	tsdPtr->inPostMenu--;
	return result;
    }








    /*
     * The post commands could have deleted the menu, which means
     * we are dead and should go away.
     */

    if (menuPtr->tkwin == NULL) {







|
>
>
>














|











<







>
>
>
>
>
>
>







739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
}

/*
 *----------------------------------------------------------------------
 *
 * TkpPostMenu --
 *
 *	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.
 *
 * Side effects:
 *	The menu is posted and handled.
 *
 *----------------------------------------------------------------------
 */

int
TkpPostMenu(
    Tcl_Interp *interp,
    TkMenu *menuPtr,
    int x, int y, int index)
{
    HMENU winMenuHdl = (HMENU) menuPtr->platformData;
    int result, flags;
    RECT noGoawayRect;
    POINT point;
    Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
    int oldServiceMode = Tcl_GetServiceMode();
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    tsdPtr->inPostMenu++;

    CallPendingReconfigureImmediately(menuPtr);

    result = TkPreprocessMenu(menuPtr);
    if (result != TCL_OK) {
	tsdPtr->inPostMenu--;
	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.
     */

    if (menuPtr->tkwin == NULL) {
833
834
835
836
837
838
839






























































































840
841
842
843
844
845
846
    Tk_PointerEvent(NULL, point.x, point.y);

    if (tsdPtr->inPostMenu) {
	tsdPtr->inPostMenu = 0;
    }
    return TCL_OK;
}































































































/*
 *----------------------------------------------------------------------
 *
 * TkpMenuNewEntry --
 *
 *	Adds a pointer to a new menu entry structure with the platform-







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
    Tk_PointerEvent(NULL, point.x, point.y);

    if (tsdPtr->inPostMenu) {
	tsdPtr->inPostMenu = 0;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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-
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
	    GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
	    	    fmPtr, &width, &height);
	    menuPtr->entries[i]->height = height;
	} else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {
	    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
	     * entry, plus three widths: the width of the label, the width to
	     * allow for an indicator to be displayed to the left of the label
	     * (if any), and the width of the accelerator to be displayed to
	     * the right of the label (if any). These sizes depend, of course,







<







3011
3012
3013
3014
3015
3016
3017

3018
3019
3020
3021
3022
3023
3024
	    GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
	    	    fmPtr, &width, &height);
	    menuPtr->entries[i]->height = height;
	} else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {
	    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
	     * entry, plus three widths: the width of the label, the width to
	     * allow for an indicator to be displayed to the left of the label
	     * (if any), and the width of the accelerator to be displayed to
	     * the right of the label (if any). These sizes depend, of course,
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
    windowWidth = x + indicatorSpace + labelWidth + accelWidth
	    + 2 * activeBorderWidth + borderWidth;


    windowHeight += borderWidth;

    /*
     * The X server doesn't like zero dimensions, so round up to at least 1 (a
     * zero-sized menu should never really occur, anyway).
     */








<
<







3068
3069
3070
3071
3072
3073
3074


3075
3076
3077
3078
3079
3080
3081
	menuPtr->entries[j]->width = indicatorSpace + labelWidth
		+ accelWidth + 2 * activeBorderWidth;
	menuPtr->entries[j]->x = x;
	menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
    }
    windowWidth = x + indicatorSpace + labelWidth + accelWidth
	    + 2 * activeBorderWidth + borderWidth;


    windowHeight += borderWidth;

    /*
     * The X server doesn't like zero dimensions, so round up to at least 1 (a
     * zero-sized menu should never really occur, anyway).
     */