summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Deily <nad@acm.org>2014-03-27 20:49:14 -0700
committerNed Deily <nad@acm.org>2014-03-27 20:49:14 -0700
commitc7059865f5c6517bca6a1d6a3de8d010abee7aeb (patch)
treefc71ec709e14dfa0f0afc8cba0723e22332bf78c
parent54ba0a7e9994587bb12cae8e3d74dd54e0fc0e21 (diff)
downloadcpython-c7059865f5c6517bca6a1d6a3de8d010abee7aeb.tar.gz
Issue #17654: Ensure IDLE menus are customized properly on OS X for
non-framework builds and for all variants of Tk.
-rw-r--r--Lib/idlelib/Bindings.py32
-rw-r--r--Lib/idlelib/Debugger.py2
-rw-r--r--Lib/idlelib/EditorWindow.py14
-rw-r--r--Lib/idlelib/MultiCall.py3
-rwxr-xr-xLib/idlelib/PyShell.py4
-rw-r--r--Lib/idlelib/ScriptBinding.py4
-rw-r--r--Lib/idlelib/ZoomHeight.py2
-rw-r--r--Lib/idlelib/configDialog.py2
-rw-r--r--Lib/idlelib/configHandler.py12
-rw-r--r--Lib/idlelib/keybindingDialog.py5
-rw-r--r--Lib/idlelib/macosxSupport.py136
-rw-r--r--Misc/NEWS6
12 files changed, 129 insertions, 93 deletions
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py
index 65c0317e60..df2b251426 100644
--- a/Lib/idlelib/Bindings.py
+++ b/Lib/idlelib/Bindings.py
@@ -8,9 +8,14 @@ the PythonShell window, and a Format menu which is only present in the Editor
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 @@ 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()
-
-del sys
diff --git a/Lib/idlelib/Debugger.py b/Lib/idlelib/Debugger.py
index d4872ed42a..ca98b107c4 100644
--- a/Lib/idlelib/Debugger.py
+++ b/Lib/idlelib/Debugger.py
@@ -322,7 +322,7 @@ class Debugger:
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
index d18305783a..cdb67750f3 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -109,8 +109,8 @@ class EditorWindow(object):
'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.base_prefix,
'Resources/English.lproj/Documentation/index.html')
dochome = os.path.normpath(dochome)
@@ -166,7 +166,7 @@ class EditorWindow(object):
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,
@@ -409,7 +409,7 @@ class EditorWindow(object):
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)
@@ -436,7 +436,7 @@ class EditorWindow(object):
("help", "_Help"),
]
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
menu_specs[-2] = ("windows", "_Window")
@@ -447,7 +447,7 @@ class EditorWindow(object):
underline, label = prepstr(label)
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)
@@ -1673,7 +1673,7 @@ def get_accelerator(keydefs, eventname):
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
index 25105dc93e..cc6bffd50d 100644
--- a/Lib/idlelib/MultiCall.py
+++ b/Lib/idlelib/MultiCall.py
@@ -32,7 +32,6 @@ Each function will be called at most once for each event.
import sys
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;
@@ -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
# 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
index e8890d1746..c23b62abd9 100755
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -844,7 +844,7 @@ class PyShell(OutputWindow):
("help", "_Help"),
]
- if macosxSupport.runningAsOSXApp():
+ if sys.platform == "darwin":
menu_specs[-2] = ("windows", "_Window")
@@ -1560,7 +1560,7 @@ def main():
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
index 6bfe128e3c..b78363708f 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -53,7 +53,7 @@ class ScriptBinding:
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):
@@ -114,7 +114,7 @@ class ScriptBinding:
shell.set_warning_stream(saved_stream)
def run_module_event(self, event):
- 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
index e8d1710751..a5d679e499 100644
--- a/Lib/idlelib/ZoomHeight.py
+++ b/Lib/idlelib/ZoomHeight.py
@@ -32,7 +32,7 @@ def zoom_height(top):
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
index efe5c4326c..fefe42b94e 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -74,7 +74,7 @@ class ConfigDialog(Toplevel):
frameActionButtons = Frame(self,pady=2)
#action buttons
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isAquaTk():
# Surpress the padx and pady arguments when
# running as IDLE.app, otherwise the text
# on these buttons will not be readable.
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
index ea2010edec..8608f7c869 100644
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -20,7 +20,6 @@ configuration problem notification and resolution.
import os
import sys
-from idlelib import macosxSupport
from configparser import ConfigParser, NoOptionError, NoSectionError
class InvalidConfigType(Exception): pass
@@ -527,10 +526,13 @@ class IdleConf:
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
index 0f0da8c7e9..db88cb4365 100644
--- a/Lib/idlelib/keybindingDialog.py
+++ b/Lib/idlelib/keybindingDialog.py
@@ -4,7 +4,7 @@ Dialog for building Tkinter accelerator key bindings
from tkinter import *
import tkinter.messagebox as tkMessageBox
import string
-from idlelib import macosxSupport
+import sys
class GetKeysDialog(Toplevel):
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
config-keys.def must use the same ordering.
"""
- import sys
- 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
index 67069fa0f3..b6488f84ca 100644
--- a/Lib/idlelib/macosxSupport.py
+++ b/Lib/idlelib/macosxSupport.py
@@ -1,48 +1,70 @@
"""
-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
+import warnings
+def runningAsOSXApp():
+ warnings.warn("runningAsOSXApp() is deprecated, use isAquaTk()",
+ DeprecationWarning, stacklevel=2)
+ return isAquaTk()
-_appbundle = None
+def isCarbonAquaTk(root):
+ warnings.warn("isCarbonAquaTk(root) is deprecated, use isCarbonTk()",
+ DeprecationWarning, stacklevel=2)
+ return isCarbonTk()
-def runningAsOSXApp():
+_tk_type = None
+
+def _initializeTkVariantTests(root):
+ """
+ Initializes OS X Tk variant values for
+ isAquaTk(), isCarbonTk(), isCocoaTk(), and isXQuartz().
"""
- Returns True if Python is running from within an app on OSX.
- If so, the various OS X customizations will be triggered later (menu
- 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
+ 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 isCarbonAquaTk(root):
+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):
"""
@@ -53,8 +75,7 @@ def tkVersionWarning(root):
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
@@ -88,8 +109,8 @@ def hideTkConsole(root):
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
@@ -108,6 +129,22 @@ def overrideRootMenu(root, flist):
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 = {}
@@ -156,7 +193,7 @@ def overrideRootMenu(root, flist):
# 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)
@@ -171,8 +208,7 @@ def overrideRootMenu(root, flist):
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
@@ -182,10 +218,22 @@ def overrideRootMenu(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()
+
+ 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
index 5240f6997f..6b0fa75b3a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -94,6 +94,12 @@ Library
(Original patches by Hirokazu Yamamoto and Amaury Forgeot d'Arc, with
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
-------------