[Python-checkins] cpython (2.7): Issue #17654: Ensure IDLE menus are customized properly on OS X for

ned.deily python-checkins at python.org
Fri Mar 28 04:52:04 CET 2014


http://hg.python.org/cpython/rev/f551740c26b6
changeset: 90005:f551740c26b6
branch: 2.7
parent: 90002:74faca1ac59c
user: Ned Deily <nad at acm.org>
date: Thu Mar 27 20:47:04 2014 -0700
summary:
 Issue #17654: Ensure IDLE menus are customized properly on OS X for
non-framework builds and for all variants of Tk.
files:
 Lib/idlelib/Bindings.py | 32 +---
 Lib/idlelib/Debugger.py | 2 +-
 Lib/idlelib/EditorWindow.py | 14 +-
 Lib/idlelib/MultiCall.py | 3 +-
 Lib/idlelib/PyShell.py | 4 +-
 Lib/idlelib/ScriptBinding.py | 4 +-
 Lib/idlelib/ZoomHeight.py | 2 +-
 Lib/idlelib/configDialog.py | 2 +-
 Lib/idlelib/configHandler.py | 12 +-
 Lib/idlelib/keybindingDialog.py | 4 +-
 Lib/idlelib/macosxSupport.py | 126 ++++++++++++++-----
 Misc/NEWS | 3 +
 12 files changed, 127 insertions(+), 81 deletions(-)
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py
--- a/Lib/idlelib/Bindings.py
+++ b/Lib/idlelib/Bindings.py
@@ -8,9 +8,14 @@
 windows.
 
 """
-import sys
 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 = [
 # underscore prefixes character to underscore
@@ -81,27 +86,4 @@
 ]),
 ]
 
-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()
-
-del sys
diff --git a/Lib/idlelib/Debugger.py b/Lib/idlelib/Debugger.py
--- a/Lib/idlelib/Debugger.py
+++ b/Lib/idlelib/Debugger.py
@@ -323,7 +323,7 @@
 class StackViewer(ScrolledList):
 
 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
 # get an shaking GUI that eventually kills IDLE if the width
 # argument is specified.
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -138,8 +138,8 @@
 'Python%s.chm' % _sphinx_version())
 if os.path.isfile(chmfile):
 dochome = chmfile
- elif macosxSupport.runningAsOSXApp():
- # documentation is stored inside the python framework
+ elif sys.platform == 'darwin':
+ # documentation may be stored inside a python framework
 dochome = os.path.join(sys.prefix,
 'Resources/English.lproj/Documentation/index.html')
 dochome = os.path.normpath(dochome)
@@ -193,7 +193,7 @@
 
 self.top.protocol("WM_DELETE_WINDOW", self.close)
 self.top.bind("<<close-window>>", self.close_event)
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isAquaTk():
 # Command-W on editorwindows doesn't work without this.
 text.bind('<<close-window>>', self.close_event)
 # Some OS X systems have only one mouse button,
@@ -440,7 +440,7 @@
 
 def set_status_bar(self):
 self.status_bar = self.MultiStatusBar(self.top)
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
 # Insert some padding to avoid obscuring some of the statusbar
 # by the resize widget.
 self.status_bar.set_label('_padding1', ' ', side=RIGHT)
@@ -467,7 +467,7 @@
 ("help", "_Help"),
 ]
 
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
 menu_specs[-2] = ("windows", "_Window")
 
 
@@ -479,7 +479,7 @@
 menudict[name] = menu = Menu(mbar, name=name)
 mbar.add_cascade(label=label, menu=menu, underline=underline)
 
- if macosxSupport.isCarbonAquaTk(self.root):
+ if macosxSupport.isCarbonTk():
 # Insert the application menu
 menudict['application'] = menu = Menu(mbar, name='apple')
 mbar.add_cascade(label='IDLE', menu=menu)
@@ -1682,7 +1682,7 @@
 keylist = keydefs.get(eventname)
 # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5
 # if not keylist:
- if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in {
+ if (not keylist) or (macosxSupport.isCocoaTk() and eventname in {
 "<<open-module>>",
 "<<goto-line>>",
 "<<change-indentwidth>>"}):
diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py
--- a/Lib/idlelib/MultiCall.py
+++ b/Lib/idlelib/MultiCall.py
@@ -33,7 +33,6 @@
 import string
 import re
 import Tkinter
-from idlelib import macosxSupport
 
 # the event type constants, which define the meaning of mc_type
 MC_KEYPRESS=0; MC_KEYRELEASE=1; MC_BUTTONPRESS=2; MC_BUTTONRELEASE=3;
@@ -46,7 +45,7 @@
 MC_OPTION = 1<<6; MC_COMMAND = 1<<7
 
 # define the list of modifiers, to be used in complex event types.
-if macosxSupport.runningAsOSXApp():
+if sys.platform == "darwin":
 _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",))
 _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND)
 else:
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -866,7 +866,7 @@
 ("help", "_Help"),
 ]
 
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
 menu_specs[-2] = ("windows", "_Window")
 
 
@@ -1566,7 +1566,7 @@
 shell = flist.open_shell()
 if not 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
 # IDLE to be launched the shell window will open just in front of
 # the file she wants to see. Lower the interpreter window when
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -54,7 +54,7 @@
 self.flist = self.editwin.flist
 self.root = self.editwin.root
 
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isCocoaTk():
 self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
 
 def check_module_event(self, event):
@@ -168,7 +168,7 @@
 interp.runcode(code)
 return 'break'
 
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isCocoaTk():
 # Tk-Cocoa in MacOSX is broken until at least
 # Tk 8.5.9, and without this rather
 # crude workaround IDLE would hang when a user
diff --git a/Lib/idlelib/ZoomHeight.py b/Lib/idlelib/ZoomHeight.py
--- a/Lib/idlelib/ZoomHeight.py
+++ b/Lib/idlelib/ZoomHeight.py
@@ -32,7 +32,7 @@
 newy = 0
 newheight = newheight - 72
 
- elif macosxSupport.runningAsOSXApp():
+ elif macosxSupport.isAquaTk():
 # 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
 # to calculate the correct value for this with tkinter.
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -71,7 +71,7 @@
 page_names=['Fonts/Tabs','Highlighting','Keys','General'])
 frameActionButtons = Frame(self,pady=2)
 #action buttons
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isAquaTk():
 # Changing the default padding on OSX results in unreadable
 # text in the buttons
 paddingArgs={}
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -20,7 +20,6 @@
 import os
 import sys
 import string
-from idlelib import macosxSupport
 from ConfigParser import ConfigParser, NoOptionError, NoSectionError
 
 class InvalidConfigType(Exception): pass
@@ -526,10 +525,13 @@
 def GetCurrentKeySet(self):
 result = self.GetKeySet(self.CurrentKeys())
 
- if macosxSupport.runningAsOSXApp():
- # We're using AquaTk, replace all keybingings that use the
- # Alt key by ones that use the Option key because the former
- # don't work reliably.
+ if sys.platform == "darwin":
+ # OS X Tk variants do not support the "Alt" keyboard modifier.
+ # So replace all keybingings that use "Alt" with ones that
+ # 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():
 v2 = [ x.replace('<Alt-', '<Option-') for x in v ]
 if v != v2:
diff --git a/Lib/idlelib/keybindingDialog.py b/Lib/idlelib/keybindingDialog.py
--- a/Lib/idlelib/keybindingDialog.py
+++ b/Lib/idlelib/keybindingDialog.py
@@ -4,6 +4,7 @@
 from Tkinter import *
 import tkMessageBox
 import string
+import sys
 
 class GetKeysDialog(Toplevel):
 def __init__(self,parent,title,action,currentKeySequences):
@@ -132,8 +133,7 @@
 order is also important: key binding equality depends on it, so
 config-keys.def must use the same ordering.
 """
- from idlelib import macosxSupport
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
 self.modifiers = ['Shift', 'Control', 'Option', 'Command']
 else:
 self.modifiers = ['Control', 'Alt', 'Shift']
diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py
--- a/Lib/idlelib/macosxSupport.py
+++ b/Lib/idlelib/macosxSupport.py
@@ -1,38 +1,72 @@
 """
-A number of function that enhance IDLE on MacOSX when it used as a normal
-GUI application (as opposed to an X11 application).
+A number of functions that enhance IDLE on Mac OSX.
 """
 import sys
 import Tkinter
 from os import path
 
 
-_appbundle = None
+import warnings
 
 def runningAsOSXApp():
- """
- Returns True if Python is running from within an app on OSX.
- If so, assume that Python was built with Aqua Tcl/Tk rather than
- X11 Tcl/Tk.
- """
- global _appbundle
- if _appbundle is None:
- _appbundle = (sys.platform == 'darwin' and '.app' in sys.executable)
- return _appbundle
-
-_carbonaquatk = None
+ warnings.warn("runningAsOSXApp() is deprecated, use isAquaTk()",
+ DeprecationWarning, stacklevel=2)
+ return isAquaTk()
 
 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
 newer Cocoa Aqua Tk).
 """
- global _carbonaquatk
- if _carbonaquatk is None:
- _carbonaquatk = (runningAsOSXApp() and
- 'aqua' in root.tk.call('tk', 'windowingsystem') and
- 'AppKit' not in root.tk.call('winfo', 'server', '.'))
- return _carbonaquatk
+ assert _tk_type is not None
+ return _tk_type == "carbon"
+
+def isCocoaTk():
+ """
+ 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):
 """
@@ -43,8 +77,7 @@
 can still crash unexpectedly.
 """
 
- if (runningAsOSXApp() and
- ('AppKit' in root.tk.call('winfo', 'server', '.')) ):
+ if isCocoaTk():
 patchlevel = root.tk.call('info', 'patchlevel')
 if patchlevel not in ('8.5.7', '8.5.9'):
 return False
@@ -78,8 +111,8 @@
 
 def overrideRootMenu(root, flist):
 """
- Replace the Tk root menu by something that's more appropriate for
- IDLE.
+ 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
@@ -98,6 +131,22 @@
 from idlelib import WindowList
 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)
 root.configure(menu=menubar)
 menudict = {}
@@ -140,7 +189,7 @@
 # right thing for now.
 root.createcommand('exit', flist.close_all_callback)
 
- if isCarbonAquaTk(root):
+ if isCarbonTk():
 # for Carbon AquaTk, replace the default Tk apple menu
 menudict['application'] = menu = Menu(menubar, name='apple')
 menubar.add_cascade(label='IDLE', menu=menu)
@@ -155,8 +204,7 @@
 Bindings.menudefs[0][1].append(
 ('_Preferences....', '<<open-config-dialog>>'),
 )
- else:
- # assume Cocoa AquaTk
+ if isCocoaTk():
 # replace default About dialog with About IDLE one
 root.createcommand('tkAboutDialog', about_dialog)
 # replace default "Help" item in Help menu
@@ -166,10 +214,22 @@
 
 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()
+
+ 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.
 """
- if not runningAsOSXApp(): return
-
- hideTkConsole(root)
- overrideRootMenu(root, flist)
- addOpenEventSupport(root, flist)
+ _initializeTkVariantTests(root)
+ if isAquaTk():
+ hideTkConsole(root)
+ overrideRootMenu(root, flist)
+ addOpenEventSupport(root, flist)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -279,6 +279,9 @@
 - Issue #18270: Prevent possible IDLE AttributeError on OS X when no initial
 shell window is present.
 
+- Issue #17654: Ensure IDLE menus are customized properly on OS X for
+ non-framework builds and for all variants of Tk.
+
 Tests
 -----
 
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /