Issue #17654: merge from 3.4

This commit is contained in:
Ned Deily 2014-03-27 20:51:15 -07:00
commit c318288f69
12 changed files with 130 additions and 94 deletions

View File

@ -8,9 +8,14 @@ the PythonShell window, and a Format menu which is only present in the Editor
windows. windows.
""" """
import sys
from idlelib.configHandler import idleConf from idlelib.configHandler import idleConf
from idlelib import macosxSupport
# Warning: menudefs is altered in macosxSupport.overrideRootMenu()
# after it is determined that an OS X Aqua Tk is in use,
# which cannot be done until after Tk() is first called.
# Do not alter the 'file', 'options', or 'help' cascades here
# without altering overrideRootMenu() as well.
# TODO: Make this more robust
menudefs = [ menudefs = [
# underscore prefixes character to underscore # underscore prefixes character to underscore
@ -81,27 +86,4 @@ menudefs = [
]), ]),
] ]
if macosxSupport.runningAsOSXApp():
# Running as a proper MacOS application bundle. This block restructures
# the menus a little to make them conform better to the HIG.
quitItem = menudefs[0][1][-1]
closeItem = menudefs[0][1][-2]
# 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.
del menudefs[0][1][-3:]
menudefs[0][1].insert(6, closeItem)
# Remove the 'About' entry from the help menu, it is in the application
# menu
del menudefs[-1][1][0:2]
# Remove the 'Configure' entry from the options menu, it is in the
# application menu as 'Preferences'
del menudefs[-2][1][0:2]
default_keydefs = idleConf.GetCurrentKeySet() default_keydefs = idleConf.GetCurrentKeySet()
del sys

View File

@ -322,7 +322,7 @@ class Debugger:
class StackViewer(ScrolledList): class StackViewer(ScrolledList):
def __init__(self, master, flist, gui): def __init__(self, master, flist, gui):
if macosxSupport.runningAsOSXApp(): if macosxSupport.isAquaTk():
# At least on with the stock AquaTk version on OSX 10.4 you'll # At least on with the stock AquaTk version on OSX 10.4 you'll
# get an shaking GUI that eventually kills IDLE if the width # get an shaking GUI that eventually kills IDLE if the width
# argument is specified. # argument is specified.

View File

@ -109,8 +109,8 @@ class EditorWindow(object):
'Python%s.chm' % _sphinx_version()) 'Python%s.chm' % _sphinx_version())
if os.path.isfile(chmfile): if os.path.isfile(chmfile):
dochome = chmfile dochome = chmfile
elif macosxSupport.runningAsOSXApp(): elif sys.platform == 'darwin':
# documentation is stored inside the python framework # documentation may be stored inside a python framework
dochome = os.path.join(sys.base_prefix, dochome = os.path.join(sys.base_prefix,
'Resources/English.lproj/Documentation/index.html') 'Resources/English.lproj/Documentation/index.html')
dochome = os.path.normpath(dochome) dochome = os.path.normpath(dochome)
@ -166,7 +166,7 @@ class EditorWindow(object):
self.top.protocol("WM_DELETE_WINDOW", self.close) self.top.protocol("WM_DELETE_WINDOW", self.close)
self.top.bind("<<close-window>>", self.close_event) self.top.bind("<<close-window>>", self.close_event)
if macosxSupport.runningAsOSXApp(): if macosxSupport.isAquaTk():
# Command-W on editorwindows doesn't work without this. # Command-W on editorwindows doesn't work without this.
text.bind('<<close-window>>', self.close_event) text.bind('<<close-window>>', self.close_event)
# Some OS X systems have only one mouse button, # Some OS X systems have only one mouse button,
@ -409,7 +409,7 @@ class EditorWindow(object):
def set_status_bar(self): def set_status_bar(self):
self.status_bar = self.MultiStatusBar(self.top) self.status_bar = self.MultiStatusBar(self.top)
if macosxSupport.runningAsOSXApp(): if sys.platform == "darwin":
# Insert some padding to avoid obscuring some of the statusbar # Insert some padding to avoid obscuring some of the statusbar
# by the resize widget. # by the resize widget.
self.status_bar.set_label('_padding1', ' ', side=RIGHT) self.status_bar.set_label('_padding1', ' ', side=RIGHT)
@ -436,7 +436,7 @@ class EditorWindow(object):
("help", "_Help"), ("help", "_Help"),
] ]
if macosxSupport.runningAsOSXApp(): if sys.platform == "darwin":
menu_specs[-2] = ("windows", "_Window") menu_specs[-2] = ("windows", "_Window")
@ -447,7 +447,7 @@ class EditorWindow(object):
underline, label = prepstr(label) underline, label = prepstr(label)
menudict[name] = menu = Menu(mbar, name=name) menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline) mbar.add_cascade(label=label, menu=menu, underline=underline)
if macosxSupport.isCarbonAquaTk(self.root): if macosxSupport.isCarbonTk():
# Insert the application menu # Insert the application menu
menudict['application'] = menu = Menu(mbar, name='apple') menudict['application'] = menu = Menu(mbar, name='apple')
mbar.add_cascade(label='IDLE', menu=menu) mbar.add_cascade(label='IDLE', menu=menu)
@ -1673,7 +1673,7 @@ def get_accelerator(keydefs, eventname):
keylist = keydefs.get(eventname) keylist = keydefs.get(eventname)
# issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5 # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5
# if not keylist: # if not keylist:
if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in { if (not keylist) or (macosxSupport.isCocoaTk() and eventname in {
"<<open-module>>", "<<open-module>>",
"<<goto-line>>", "<<goto-line>>",
"<<change-indentwidth>>"}): "<<change-indentwidth>>"}):

View File

@ -32,7 +32,6 @@ Each function will be called at most once for each event.
import sys import sys
import re import re
import tkinter import tkinter
from idlelib import macosxSupport
# the event type constants, which define the meaning of mc_type # the event type constants, which define the meaning of mc_type
MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3; MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3;
@ -45,7 +44,7 @@ MC_SHIFT = 1<<0; MC_CONTROL = 1<<2; MC_ALT = 1<<3; MC_META = 1<<5
MC_OPTION = 1<<6; MC_COMMAND = 1<<7 MC_OPTION = 1<<6; MC_COMMAND = 1<<7
# define the list of modifiers, to be used in complex event types. # define the list of modifiers, to be used in complex event types.
if macosxSupport.runningAsOSXApp(): if sys.platform == "darwin":
_modifiers = (("Shift",), ("Control",), ("Option",), ("Command",)) _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",))
_modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND) _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND)
else: else:

View File

@ -844,7 +844,7 @@ class PyShell(OutputWindow):
("help", "_Help"), ("help", "_Help"),
] ]
if macosxSupport.runningAsOSXApp(): if sys.platform == "darwin":
menu_specs[-2] = ("windows", "_Window") menu_specs[-2] = ("windows", "_Window")
@ -1560,7 +1560,7 @@ def main():
shell = flist.open_shell() shell = flist.open_shell()
if not shell: if not shell:
return # couldn't open shell return # couldn't open shell
if macosxSupport.runningAsOSXApp() and flist.dict: if macosxSupport.isAquaTk() and flist.dict:
# On OSX: when the user has double-clicked on a file that causes # On OSX: when the user has double-clicked on a file that causes
# IDLE to be launched the shell window will open just in front of # IDLE to be launched the shell window will open just in front of
# the file she wants to see. Lower the interpreter window when # the file she wants to see. Lower the interpreter window when

View File

@ -53,7 +53,7 @@ class ScriptBinding:
self.flist = self.editwin.flist self.flist = self.editwin.flist
self.root = self.editwin.root self.root = self.editwin.root
if macosxSupport.runningAsOSXApp(): if macosxSupport.isCocoaTk():
self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event) self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
def check_module_event(self, event): def check_module_event(self, event):
@ -114,7 +114,7 @@ class ScriptBinding:
shell.set_warning_stream(saved_stream) shell.set_warning_stream(saved_stream)
def run_module_event(self, event): def run_module_event(self, event):
if macosxSupport.runningAsOSXApp(): if macosxSupport.isCocoaTk():
# Tk-Cocoa in MacOSX is broken until at least # Tk-Cocoa in MacOSX is broken until at least
# Tk 8.5.9, and without this rather # Tk 8.5.9, and without this rather
# crude workaround IDLE would hang when a user # crude workaround IDLE would hang when a user

View File

@ -32,7 +32,7 @@ def zoom_height(top):
newy = 0 newy = 0
newheight = newheight - 72 newheight = newheight - 72
elif macosxSupport.runningAsOSXApp(): elif macosxSupport.isAquaTk():
# The '88' below is a magic number that avoids placing the bottom # The '88' below is a magic number that avoids placing the bottom
# of the window below the panel on my machine. I don't know how # of the window below the panel on my machine. I don't know how
# to calculate the correct value for this with tkinter. # to calculate the correct value for this with tkinter.

View File

@ -74,7 +74,7 @@ class ConfigDialog(Toplevel):
frameActionButtons = Frame(self,pady=2) frameActionButtons = Frame(self,pady=2)
#action buttons #action buttons
if macosxSupport.runningAsOSXApp(): if macosxSupport.isAquaTk():
# Surpress the padx and pady arguments when # Surpress the padx and pady arguments when
# running as IDLE.app, otherwise the text # running as IDLE.app, otherwise the text
# on these buttons will not be readable. # on these buttons will not be readable.

View File

@ -20,7 +20,6 @@ configuration problem notification and resolution.
import os import os
import sys import sys
from idlelib import macosxSupport
from configparser import ConfigParser, NoOptionError, NoSectionError from configparser import ConfigParser, NoOptionError, NoSectionError
class InvalidConfigType(Exception): pass class InvalidConfigType(Exception): pass
@ -527,10 +526,13 @@ class IdleConf:
def GetCurrentKeySet(self): def GetCurrentKeySet(self):
result = self.GetKeySet(self.CurrentKeys()) result = self.GetKeySet(self.CurrentKeys())
if macosxSupport.runningAsOSXApp(): if sys.platform == "darwin":
# We're using AquaTk, replace all keybingings that use the # OS X Tk variants do not support the "Alt" keyboard modifier.
# Alt key by ones that use the Option key because the former # So replace all keybingings that use "Alt" with ones that
# don't work reliably. # use the "Option" keyboard modifier.
# TO DO: the "Option" modifier does not work properly for
# Cocoa Tk and XQuartz Tk so we should not use it
# in default OS X KeySets.
for k, v in result.items(): for k, v in result.items():
v2 = [ x.replace('<Alt-', '<Option-') for x in v ] v2 = [ x.replace('<Alt-', '<Option-') for x in v ]
if v != v2: if v != v2:

View File

@ -4,7 +4,7 @@ Dialog for building Tkinter accelerator key bindings
from tkinter import * from tkinter import *
import tkinter.messagebox as tkMessageBox import tkinter.messagebox as tkMessageBox
import string import string
from idlelib import macosxSupport import sys
class GetKeysDialog(Toplevel): class GetKeysDialog(Toplevel):
def __init__(self,parent,title,action,currentKeySequences): def __init__(self,parent,title,action,currentKeySequences):
@ -133,8 +133,7 @@ class GetKeysDialog(Toplevel):
order is also important: key binding equality depends on it, so order is also important: key binding equality depends on it, so
config-keys.def must use the same ordering. config-keys.def must use the same ordering.
""" """
import sys if sys.platform == "darwin":
if macosxSupport.runningAsOSXApp():
self.modifiers = ['Shift', 'Control', 'Option', 'Command'] self.modifiers = ['Shift', 'Control', 'Option', 'Command']
else: else:
self.modifiers = ['Control', 'Alt', 'Shift'] self.modifiers = ['Control', 'Alt', 'Shift']

View File

@ -1,48 +1,70 @@
""" """
A number of function that enhance IDLE on MacOSX when it used as a normal A number of functions that enhance IDLE on Mac OSX.
GUI application (as opposed to an X11 application).
""" """
import sys import sys
import tkinter import tkinter
from os import path from os import path
import warnings
_appbundle = None
def runningAsOSXApp(): def runningAsOSXApp():
""" warnings.warn("runningAsOSXApp() is deprecated, use isAquaTk()",
Returns True if Python is running from within an app on OSX. DeprecationWarning, stacklevel=2)
If so, the various OS X customizations will be triggered later (menu return isAquaTk()
fixup, et al). (Originally, this test was supposed to condition
behavior on whether IDLE was running under Aqua Tk rather than
under X11 Tk but that does not work since a framework build
could be linked with X11. For several releases, this test actually
differentiates between whether IDLE is running from a framework or
not. As a future enhancement, it should be considered whether there
should be a difference based on framework and any needed X11 adaptions
should be made dependent on a new function that actually tests for X11.)
"""
global _appbundle
if _appbundle is None:
_appbundle = sys.platform == 'darwin'
if _appbundle:
import sysconfig
_appbundle = bool(sysconfig.get_config_var('PYTHONFRAMEWORK'))
return _appbundle
_carbonaquatk = None
def isCarbonAquaTk(root): def isCarbonAquaTk(root):
warnings.warn("isCarbonAquaTk(root) is deprecated, use isCarbonTk()",
DeprecationWarning, stacklevel=2)
return isCarbonTk()
_tk_type = None
def _initializeTkVariantTests(root):
"""
Initializes OS X Tk variant values for
isAquaTk(), isCarbonTk(), isCocoaTk(), and isXQuartz().
"""
global _tk_type
if sys.platform == 'darwin':
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"
else:
_tk_type = "other"
def isAquaTk():
"""
Returns True if IDLE is using a native OS X Tk (Cocoa or Carbon).
"""
assert _tk_type is not None
return _tk_type == "cocoa" or _tk_type == "carbon"
def isCarbonTk():
""" """
Returns True if IDLE is using a Carbon Aqua Tk (instead of the Returns True if IDLE is using a Carbon Aqua Tk (instead of the
newer Cocoa Aqua Tk). newer Cocoa Aqua Tk).
""" """
global _carbonaquatk assert _tk_type is not None
if _carbonaquatk is None: return _tk_type == "carbon"
_carbonaquatk = (runningAsOSXApp() and
'aqua' in root.tk.call('tk', 'windowingsystem') and def isCocoaTk():
'AppKit' not in root.tk.call('winfo', 'server', '.')) """
return _carbonaquatk Returns True if IDLE is using a Cocoa Aqua Tk.
"""
assert _tk_type is not None
return _tk_type == "cocoa"
def isXQuartz():
"""
Returns True if IDLE is using an OS X X11 Tk.
"""
assert _tk_type is not None
return _tk_type == "xquartz"
def tkVersionWarning(root): def tkVersionWarning(root):
""" """
@ -53,8 +75,7 @@ def tkVersionWarning(root):
can still crash unexpectedly. can still crash unexpectedly.
""" """
if (runningAsOSXApp() and if isCocoaTk():
('AppKit' in root.tk.call('winfo', 'server', '.')) ):
patchlevel = root.tk.call('info', 'patchlevel') patchlevel = root.tk.call('info', 'patchlevel')
if patchlevel not in ('8.5.7', '8.5.9'): if patchlevel not in ('8.5.7', '8.5.9'):
return False return False
@ -88,8 +109,8 @@ def hideTkConsole(root):
def overrideRootMenu(root, flist): def overrideRootMenu(root, flist):
""" """
Replace the Tk root menu by something that's more appropriate for Replace the Tk root menu by something that is more appropriate for
IDLE. IDLE with an Aqua Tk.
""" """
# The menu that is attached to the Tk root (".") is also used by AquaTk for # 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 # all windows that don't specify a menu of their own. The default menubar
@ -108,6 +129,22 @@ def overrideRootMenu(root, flist):
from idlelib import WindowList from idlelib import WindowList
from idlelib.MultiCall import MultiCallCreator from idlelib.MultiCall import MultiCallCreator
closeItem = Bindings.menudefs[0][1][-2]
# 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.
del Bindings.menudefs[0][1][-3:]
Bindings.menudefs[0][1].insert(6, closeItem)
# Remove the 'About' entry from the help menu, it is in the application
# menu
del Bindings.menudefs[-1][1][0:2]
# Remove the 'Configure' entry from the options menu, it is in the
# application menu as 'Preferences'
del Bindings.menudefs[-2][1][0:2]
menubar = Menu(root) menubar = Menu(root)
root.configure(menu=menubar) root.configure(menu=menubar)
menudict = {} menudict = {}
@ -156,7 +193,7 @@ def overrideRootMenu(root, flist):
# right thing for now. # right thing for now.
root.createcommand('exit', flist.close_all_callback) root.createcommand('exit', flist.close_all_callback)
if isCarbonAquaTk(root): if isCarbonTk():
# for Carbon AquaTk, replace the default Tk apple menu # for Carbon AquaTk, replace the default Tk apple menu
menudict['application'] = menu = Menu(menubar, name='apple') menudict['application'] = menu = Menu(menubar, name='apple')
menubar.add_cascade(label='IDLE', menu=menu) menubar.add_cascade(label='IDLE', menu=menu)
@ -171,8 +208,7 @@ def overrideRootMenu(root, flist):
Bindings.menudefs[0][1].append( Bindings.menudefs[0][1].append(
('_Preferences....', '<<open-config-dialog>>'), ('_Preferences....', '<<open-config-dialog>>'),
) )
else: if isCocoaTk():
# assume Cocoa AquaTk
# replace default About dialog with About IDLE one # replace default About dialog with About IDLE one
root.createcommand('tkAboutDialog', about_dialog) root.createcommand('tkAboutDialog', about_dialog)
# replace default "Help" item in Help menu # replace default "Help" item in Help menu
@ -182,10 +218,22 @@ def overrideRootMenu(root, flist):
def setupApp(root, flist): def setupApp(root, flist):
""" """
Perform setup for the OSX application bundle. Perform initial OS X customizations if needed.
""" Called from PyShell.main() after initial calls to Tk()
if not runningAsOSXApp(): return
hideTkConsole(root) There are currently three major versions of Tk in use on OS X:
overrideRootMenu(root, flist) 1. Aqua Cocoa Tk (native default since OS X 10.6)
addOpenEventSupport(root, flist) 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.
"""
_initializeTkVariantTests(root)
if isAquaTk():
hideTkConsole(root)
overrideRootMenu(root, flist)
addOpenEventSupport(root, flist)

View File

@ -124,6 +124,12 @@ Library
(Original patches by Hirokazu Yamamoto and Amaury Forgeot d'Arc, with (Original patches by Hirokazu Yamamoto and Amaury Forgeot d'Arc, with
suggested wording by David Gutteridge) suggested wording by David Gutteridge)
IDLE
----
- Issue #17654: Ensure IDLE menus are customized properly on OS X for
non-framework builds and for all variants of Tk.
Documentation Documentation
------------- -------------