]> granicus.if.org Git - python/commitdiff
Issue #17654: Ensure IDLE menus are customized properly on OS X for
authorNed Deily <nad@acm.org>
Fri, 28 Mar 2014 03:49:14 +0000 (20:49 -0700)
committerNed Deily <nad@acm.org>
Fri, 28 Mar 2014 03:49:14 +0000 (20:49 -0700)
non-framework builds and for all variants of Tk.

12 files changed:
Lib/idlelib/Bindings.py
Lib/idlelib/Debugger.py
Lib/idlelib/EditorWindow.py
Lib/idlelib/MultiCall.py
Lib/idlelib/PyShell.py
Lib/idlelib/ScriptBinding.py
Lib/idlelib/ZoomHeight.py
Lib/idlelib/configDialog.py
Lib/idlelib/configHandler.py
Lib/idlelib/keybindingDialog.py
Lib/idlelib/macosxSupport.py
Misc/NEWS

index 65c0317e60cc1bda4584077470028c371dcf67a4..df2b251426a91f5c298e3352c80a79510558a194 100644 (file)
@@ -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
index d4872ed42af8201de11c0b764e70cc243e7ba900..ca98b107c48eb8482b6b81b390bfb001afe3c3a2 100644 (file)
@@ -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.
index d18305783a893f6641489e0a387f4c90e2db6d20..cdb67750f3687eff83a030af2c0662dc66989d11 100644 (file)
@@ -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>>"}):
index 25105dc93ecb99754a28ce8359e97621ee56affb..cc6bffd50d1f11d7c5d8f3dabbcc5c085abc75d3 100644 (file)
@@ -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:
index e8890d1746e19f7c20fd37cd611190545c5428c1..c23b62abd9bc784fd3591266971972a667c3ada1 100755 (executable)
@@ -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
index 6bfe128e3ce82ce960d9bbcc66bf0e5fd3023de4..b78363708f8babec4269145f1cff0dfdb3f39179 100644 (file)
@@ -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
index e8d1710751061759bae094ecce03c48b09c37b62..a5d679e49912b5e4a9ade7340beb46c8aba17a2c 100644 (file)
@@ -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.
index efe5c4326cb0429d485a899e648720c5eda82c5a..fefe42b94e836c9b5e14e95a8f2bea7f351fcd41 100644 (file)
@@ -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.
index ea2010edeca2cfbce4fc2a3b655e7914192f6797..8608f7c869378494429793fe5a5f8903d4c3831d 100644 (file)
@@ -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:
index 0f0da8c7e930d953f906e380e4296d437c60ecfb..db88cb4365e4124b19ade1193e2f4a3d29dd457c 100644 (file)
@@ -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']
index 67069fa0f393b526855c3ee5e8b9b05c6532e060..b6488f84ca1eed3d68a2412a800920191f2fd95a 100644 (file)
@@ -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)
index 5240f6997ff77113e76c3731b56e2a1f551a715b..6b0fa75b3a393972094bcac8b0a09270c2b5cd07 100644 (file)
--- 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
 -------------