a number of functions that enhance idle on macos define functions that query the mac graphics type tktype and its initializer are private to this section initialize tktype for isxyztk functions this function is only called once when tktype is still none when running idle gui is present test may not be when running tests test is present gui may not be if not guess most common does not matter for testing returns true if idle is using a native os x tk cocoa or carbon returns true if idle is using a carbon aqua tk instead of the newer cocoa aqua tk returns true if idle is using a cocoa aqua tk returns true if idle is using an os x x11 tk fetch the macos system preferences warn if prefer tabs when opening documents is set to always fix the menu and related functions this ensures that the application will respond to open appleevents which makes is feasible to use idle as the default application for python files the command below is a hook in aquatk that is called whenever the app receives a file open event the callback can have multiple arguments one for every file that should be opened some versions of the tk framework don t have a console object replace the tk root menu by something that is more appropriate for idle with an aqua tk the menu that is attached to the tk root is also used by aquatk for all windows that don t specify a menu of their own the default menubar contains a number of menus none of which are appropriate for idle the most annoying of those is an about tcktk menu in the application menu this function replaces the default menubar by a mostly empty one it should only contain the correct application menu and the window menu due to a misfeature of tkaqua the user will also see an empty help menu remove the last 3 items of the file menu a separator close window and quit close window will be reinserted just above the save item where it should be according to the hig quit is in the application menu remove the about entry from the help menu it is in the application menu remove the configure idle entry from the options menu it is in the application menu as preferences synchronize with editor editorwindow aboutdialog synchronize with editor editorwindow configdialog ensure that the root object has an instancedict attribute mirrors code in editorwindow although that sets the attribute on an editorwindow instance that is then passed as the first argument to configdialog synchronize with editor editorwindow helpdialog the binding above doesn t reliably work on all versions of tk on macos adding command definition below does seem to do the right thing for now for carbon aquatk replace the default tk apple menu replace default about dialog with about idle one replace default help item in help menu remove redundant idle help from menu removed bad aquatk button2 right and paste bindings they prevent context menu access and seem to be gone in aquatk8 6 see issue 24801 perform initial os x customizations if needed called from pyshell main after initial calls to tk there are currently three major versions of tk in use on os x 1 aqua cocoa tk native default since os x 10 6 2 aqua carbon tk original native 32bit only deprecated 3 x11 supported by some thirdparty distributors deprecated there are various differences among the three that affect idle behavior primarily with menus mouse key events and accelerators some onetime customizations are performed here others are dynamically tested throughout idlelib by calls to the isaquatk iscarbontk iscocoatk isxquartz functions which are initialized here as well used in _init_tk_type changed by test define functions that query the mac graphics type _tk_type and its initializer are private to this section initialize _tk_type for isxyztk functions this function is only called once when _tk_type is still none when running idle gui is present test may not be when running tests test is present gui may not be if not guess most common does not matter for testing returns true if idle is using a native os x tk cocoa or carbon returns true if idle is using a carbon aqua tk instead of the newer cocoa aqua tk returns true if idle is using a cocoa aqua tk returns true if idle is using an os x x11 tk fetch the macos system preferences warn if prefer tabs when opening documents is set to always fix the menu and related functions this ensures that the application will respond to open appleevents which makes is feasible to use idle as the default application for python files the command below is a hook in aquatk that is called whenever the app receives a file open event the callback can have multiple arguments one for every file that should be opened some versions of the tk framework don t have a console object replace the tk root menu by something that is more appropriate for idle with an aqua tk the menu that is attached to the tk root is also used by aquatk for all windows that don t specify a menu of their own the default menubar contains a number of menus none of which are appropriate for idle the most annoying of those is an about tck tk menu in the application menu this function replaces the default menubar by a mostly empty one it should only contain the correct application menu and the window menu due to a mis feature of tkaqua the user will also see an empty help menu remove the last 3 items of the file menu a separator close window and quit close window will be reinserted just above the save item where it should be according to the hig quit is in the application menu remove the about entry from the help menu it is in the application menu remove the configure idle entry from the options menu it is in the application menu as preferences synchronize with editor editorwindow about_dialog synchronize with editor editorwindow config_dialog ensure that the root object has an instance_dict attribute mirrors code in editorwindow although that sets the attribute on an editorwindow instance that is then passed as the first argument to configdialog synchronize with editor editorwindow help_dialog the binding above doesn t reliably work on all versions of tk on macos adding command definition below does seem to do the right thing for now for carbon aquatk replace the default tk apple menu replace default about dialog with about idle one replace default help item in help menu remove redundant idle help from menu removed bad aquatk button 2 right and paste bindings they prevent context menu access and seem to be gone in aquatk8 6 see issue 24801 perform initial os x customizations if needed called from pyshell main after initial calls to tk there are currently three major versions of tk in use on os x 1 aqua cocoa tk native default since os x 10 6 2 aqua carbon tk original native 32 bit only deprecated 3 x11 supported by some third party distributors deprecated there are various differences among the three that affect idle behavior primarily with menus mouse key events and accelerators some one time customizations are performed here others are dynamically tested throughout idlelib by calls to the isaquatk iscarbontk iscocoatk isxquartz functions which are initialized here as well
from os.path import expanduser
import plistlib
from sys import platform  

import tkinter





_tk_type = None

def _init_tk_type():
    
    global _tk_type
    if platform == 'darwin':

        
        
        
        from idlelib.__init__ import testing
        if testing:
            from test.support import requires, ResourceDenied
            try:
                requires('gui')
            except ResourceDenied:
                _tk_type = "cocoa"
                return

        root = tkinter.Tk()
        ws = root.tk.call('tk', 'windowingsystem')
        if 'x11' in ws:
            _tk_type = "xquartz"
        elif 'aqua' not in ws:
            _tk_type = "other"
        elif 'AppKit' in root.tk.call('winfo', 'server', '.'):
            _tk_type = "cocoa"
        else:
            _tk_type = "carbon"
        root.destroy()
    else:
        _tk_type = "other"
    return

def isAquaTk():
    
    if not _tk_type:
        _init_tk_type()
    return _tk_type == "cocoa" or _tk_type == "carbon"

def isCarbonTk():
    
    if not _tk_type:
        _init_tk_type()
    return _tk_type == "carbon"

def isCocoaTk():
    
    if not _tk_type:
        _init_tk_type()
    return _tk_type == "cocoa"

def isXQuartz():
    
    if not _tk_type:
        _init_tk_type()
    return _tk_type == "xquartz"


def readSystemPreferences():
    
    if platform != 'darwin':
        return None

    plist_path = expanduser('~/Library/Preferences/.GlobalPreferences.plist')
    try:
        with open(plist_path, 'rb') as plist_file:
            return plistlib.load(plist_file)
    except OSError:
        return None


def preferTabsPreferenceWarning():
    
    if platform != 'darwin':
        return None

    prefs = readSystemPreferences()
    if prefs and prefs.get('AppleWindowTabbingMode') == 'always':
        return (
            'WARNING: The system preference "Prefer tabs when opening'
            ' documents" is set to "Always". This will cause various problems'
            ' with IDLE. For the best experience, change this setting when'
            ' running IDLE (via System Preferences -> Dock).'
        )
    return None




def addOpenEventSupport(root, flist):
    
    def doOpenFile(*args):
        for fn in args:
            flist.open(fn)

    
    
    
    root.createcommand("::tk::mac::OpenDocument", doOpenFile)

def hideTkConsole(root):
    try:
        root.tk.call('console', 'hide')
    except tkinter.TclError:
        
        pass

def overrideRootMenu(root, flist):
     
    
    from tkinter import Menu
    from idlelib import mainmenu
    from idlelib import window

    closeItem = mainmenu.menudefs[0][1][-2]
    
    del mainmenu.menudefs[0][1][-3:]
    mainmenu.menudefs[0][1].insert(6, closeItem)

    
    
    del mainmenu.menudefs[-1][1][0:2]
    
    
    del mainmenu.menudefs[-3][1][0:2]
    menubar = Menu(root)
    root.configure(menu=menubar)

    menu = Menu(menubar, name='window', tearoff=0)
    menubar.add_cascade(label='Window', menu=menu, underline=0)

    def postwindowsmenu(menu=menu):
        end = menu.index('end')
        if end is None:
            end = -1

        if end > 0:
            menu.delete(0, end)
        window.add_windows_to_menu(menu)
    window.register_callback(postwindowsmenu)

    def about_dialog(event=None):
        "Handle Help 'About IDLE' event."
        
        from idlelib import help_about
        help_about.AboutDialog(root)

    def config_dialog(event=None):
        "Handle Options 'Configure IDLE' event."
        
        from idlelib import configdialog

        
        
        
        
        root.instance_dict = flist.inversedict
        configdialog.ConfigDialog(root, 'Settings')

    def help_dialog(event=None):
        "Handle Help 'IDLE Help' event."
        
        from idlelib import help
        help.show_idlehelp(root)

    root.bind('<<about-idle>>', about_dialog)
    root.bind('<<open-config-dialog>>', config_dialog)
    root.createcommand('::tk::mac::ShowPreferences', config_dialog)
    if flist:
        root.bind('<<close-all-windows>>', flist.close_all_callback)

        
        
        
        root.createcommand('exit', flist.close_all_callback)

    if isCarbonTk():
        
        menu = Menu(menubar, name='apple', tearoff=0)
        menubar.add_cascade(label='IDLE', menu=menu)
        mainmenu.menudefs.insert(0,
            ('application', [
                ('About IDLE', '<<about-idle>>'),
                    None,
                ]))
    if isCocoaTk():
        
        root.createcommand('tkAboutDialog', about_dialog)
        
        root.createcommand('::tk::mac::ShowHelp', help_dialog)
        
        del mainmenu.menudefs[-1][1][0]

def fixb2context(root):
    
    root.unbind_class('Text', '<B2>')
    root.unbind_class('Text', '<B2-Motion>')
    root.unbind_class('Text', '<<PasteSelection>>')

def setupApp(root, flist):
    
    if isAquaTk():
        hideTkConsole(root)
        overrideRootMenu(root, flist)
        addOpenEventSupport(root, flist)
        fixb2context(root)


if __name__ == '__main__':
    from unittest import main
    main('idlelib.idle_test.test_macosx', verbosity=2)