Tk Source Code

Check-in [02587490]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Added ::tk::unsupported::MacWindowStyle appearance to control which appearances are allowed on a per-window basis.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-0d63621b6c
Files: files | file ages | folders
SHA3-256: 0258749067cda9ef8fb23cddab566e1f3c0ea7fb7953687029c9e493675fdf8c
User & Date: culler 2019-03-18 15:36:31
Context
2019-03-18
17:39
Patched up the combobox behavior, without a special drawing procedure for Dark Mode. check-in: 02dfe16c user: culler tags: bug-0d63621b6c
15:36
Added ::tk::unsupported::MacWindowStyle appearance to control which appearances are allowed on a per-window basis. check-in: 02587490 user: culler tags: bug-0d63621b6c
2019-03-17
20:40
Added a drawing procedure for dark BevelButtons. check-in: 520a121d user: culler tags: bug-0d63621b6c
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to macosx/README.

184
185
186
187
188
189
190










191
192
193
194
195
196
197
support for some legacy Carbon-specific classes and attributes was removed
(they are still accepted by the command but no longer have any effect).

- Another command available in the tk::unsupported::MacWindowStyle namespace is
tk::unsupported::MacWindowStyle tabbingid window ?newId?  which can be used to
get or set the tabbingIdentifier for the NSWindow associated with a Tk Window.
See section 3 for details.











- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.

3. FullScreen, Split View and Tabbed Windows






>
>
>
>
>
>
>
>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
support for some legacy Carbon-specific classes and attributes was removed
(they are still accepted by the command but no longer have any effect).

- Another command available in the tk::unsupported::MacWindowStyle namespace is
tk::unsupported::MacWindowStyle tabbingid window ?newId?  which can be used to
get or set the tabbingIdentifier for the NSWindow associated with a Tk Window.
See section 3 for details.

- A command tk::unsupported::MacWindowStyle appearance window ?newAappearance?
is available when Tk is built and run on macOS 10.14 (Mojave) or later.  In
that case the Ttk widgets all support the "Dark Mode" appearance which was
introduced in 10.14. The command accepts the following values for the optional
newAppearance option: "aqua", "darkaqua", or "auto".  If the appearance is set
to aqua or darkaqua then the window will be displayed with the corresponding
appearance independent of any preferences settings.  If it is set to "auto"
the appearance will be determined by the preferences.  This command can be
used to opt out of Dark Mode on a per-window basis.

- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.

3. FullScreen, Split View and Tabbed Windows

Changes to macosx/tkMacOSXWm.c.

307
308
309
310
311
312
313


314
315
316
317
318
319
320
....
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
....
5536
5537
5538
5539
5540
5541
5542
5543

5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559





5560
5561


5562





5563
5564
5565
5566
5567
5568
5569
....
5804
5805
5806
5807
5808
5809
5810



























































































5811
5812
5813
5814
5815
5816
5817
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);
static int		WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);


static void		ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
			    NSWindow *macWindow, UInt64 oldAttributes,
			    int oldFlags, int create, int initial);
static void		ApplyMasterOverrideChanges(TkWindow *winPtr,
			    NSWindow *macWindow);
static void		GetMinSize(TkWindow *winPtr, int *minWidthPtr,
			    int *minHeightPtr);
................................................................................
TkUnsupported1ObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const subcmds[] = {
	"style", "tabbingid", NULL
    };
    enum SubCmds {
	TKMWS_STYLE, TKMWS_TABID
    };
    Tk_Window tkwin = clientData;
    TkWindow *winPtr;
    int index;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
................................................................................
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], subcmds,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if (((enum SubCmds) index) == TKMWS_STYLE) {

	if ((objc < 3) || (objc > 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?");
	    return TCL_ERROR;
	}
	return WmWinStyle(interp, winPtr, objc, objv);
    } else if (((enum SubCmds) index) == TKMWS_TABID) {
	if ([NSApp macMinorVersion] < 12) {
	    Tcl_AddErrorInfo(interp,
	        "\n    (TabbingIdentifiers only exist on OSX 10.12 or later)");
	    return TCL_ERROR;
	}
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tabbingid window ?newid?");
	    return TCL_ERROR;
	}
	return WmWinTabbingId(interp, winPtr, objc, objv);





    }
    /* won't be reached */


    return TCL_ERROR;





}
 
/*
 *----------------------------------------------------------------------
 *
 * WmWinStyle --
 *
................................................................................
	 * separate window so we don't violate the rule that all tabs in the
	 * same frame must have the same tabbingIdentifier.
	 */

	if ([idString compare:newIdString] != NSOrderedSame && [win tab]) {
	    [win moveTabToNewWindow:nil];
	}



























































































	return TCL_OK;
    }
#endif
    return TCL_ERROR;
}
 
/*






>
>







 







|


|







 







|
>





|










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







 







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







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
....
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
....
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568

5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
....
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static void		WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr);
static int		WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static int		WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,
			    int objc, Tcl_Obj *const objv[]);
static void		ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
			    NSWindow *macWindow, UInt64 oldAttributes,
			    int oldFlags, int create, int initial);
static void		ApplyMasterOverrideChanges(TkWindow *winPtr,
			    NSWindow *macWindow);
static void		GetMinSize(TkWindow *winPtr, int *minWidthPtr,
			    int *minHeightPtr);
................................................................................
TkUnsupported1ObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const subcmds[] = {
	"style", "tabbingid", "appearance", NULL
    };
    enum SubCmds {
	TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE
    };
    Tk_Window tkwin = clientData;
    TkWindow *winPtr;
    int index;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
................................................................................
	return TCL_ERROR;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], subcmds,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    switch((enum SubCmds) index) {
    case TKMWS_STYLE:
	if ((objc < 3) || (objc > 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?");
	    return TCL_ERROR;
	}
	return WmWinStyle(interp, winPtr, objc, objv);
    case TKMWS_TABID:
	if ([NSApp macMinorVersion] < 12) {
	    Tcl_AddErrorInfo(interp,
	        "\n    (TabbingIdentifiers only exist on OSX 10.12 or later)");
	    return TCL_ERROR;
	}
	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tabbingid window ?newid?");
	    return TCL_ERROR;
	}
	return WmWinTabbingId(interp, winPtr, objc, objv);
    case TKMWS_APPEARANCE:
	if ([NSApp macMinorVersion] < 12) {
	    Tcl_AddErrorInfo(interp,
	        "\n    (The appearance command requires OSX 10.14 or later)");
	    return TCL_ERROR;
	}

	if ((objc < 3) || (objc > 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "appearance window ?appearancename?");
	    return TCL_ERROR;
	}
	return WmWinAppearance(interp, winPtr, objc, objv);
    default:
	return TCL_ERROR;
    }
}
 
/*
 *----------------------------------------------------------------------
 *
 * WmWinStyle --
 *
................................................................................
	 * separate window so we don't violate the rule that all tabs in the
	 * same frame must have the same tabbingIdentifier.
	 */

	if ([idString compare:newIdString] != NSOrderedSame && [win tab]) {
	    [win moveTabToNewWindow:nil];
	}
	return TCL_OK;
    }
#endif
    return TCL_ERROR;
}
 
/*
 *----------------------------------------------------------------------
 *
 * WmWinAppearance --
 *
 *	This procedure is invoked to process the
 *	"::tk::unsupported::MacWindowStyle appearance" subcommand. The command
 *	allows you to get or set the appearance for the NSWindow
 *      associated with a Tk Window.  The syntax is:
 *      tk::unsupported::MacWindowStyle tabbingid window ?newAppearance?
 *      Allowed appearance names are "aqua", "darkaqua", and "auto".
 *
 * Results:
 *      Returns the appearance setting of the window prior to calling this
 *	function.
 *
 * Side effects:
 *      The underlying NSWindow's appearance property is set to the specified
 *      value if the optional newAppearance argument is supplied. Otherwise
 *      the window's appearance property is not changed.  If the appearance is
 *      set to aqua or darkaqua then the window will use the associated
 *      NSAppearance even if the user has selected a different appearance with
 *      the system preferences.  If it is set to auto then the appearance
 *      property is set to nil, meaning that the preferences will determine the
 *      appearance.
 *
 *
 *----------------------------------------------------------------------
 */

    static int
WmWinAppearance(
    Tcl_Interp *interp,		/* Current interpreter. */
    TkWindow *winPtr,		/* Window to be manipulated. */
    int objc,			/* Number of arguments. */
    Tcl_Obj * const objv[])	/* Argument objects. */
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
    static const char *const appearanceStrings[] = {
	"aqua", "darkaqua", "auto", NULL
    };
    enum appearances {
	APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO
    };
    Tcl_Obj *result = NULL;
    NSAppearanceName appearance;
    const char *resultString;
    NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
    if (win) {
	appearance = win.appearance.name;
	if (appearance == nil) {
	    resultString = appearanceStrings[APPEARANCE_AUTO];
	} else if (appearance == NSAppearanceNameAqua) {
	    resultString = appearanceStrings[APPEARANCE_AQUA];
	} else if (appearance == NSAppearanceNameDarkAqua) {
	    resultString = appearanceStrings[APPEARANCE_DARKAQUA];
	} else {
	    resultString = "unrecognized";
	}
	result = Tcl_NewStringObj(resultString, strlen(resultString));
    }
    if (result == NULL) {
	Tcl_Panic("Failed to read appearance name.");
    }
    Tcl_SetObjResult(interp, result);
    if (objc == 3) {
	return TCL_OK;
    } else if (objc == 4) {
	int index;
	if (Tcl_GetIndexFromObjStruct(interp, objv[3], appearanceStrings,
                sizeof(char *), "appearancename", 0, &index) != TCL_OK) {
            return TCL_ERROR;
        }
	switch ((enum appearances) index) {
	case APPEARANCE_AQUA:
	    win.appearance = [NSAppearance appearanceNamed:
					       NSAppearanceNameAqua];
	    break;
	case APPEARANCE_DARKAQUA:
	    win.appearance = [NSAppearance appearanceNamed:
					       NSAppearanceNameDarkAqua];
	    break;
	default:
	    win.appearance = nil;
	}
	return TCL_OK;
    }
#endif
    return TCL_ERROR;
}
 
/*