A couple small changes are required to provide good user
experience on the mac. One of the major problems is that our
keybindings are unnatural to mac users. The two major issues
are:
- Issue 26854 - Ctrl is used as the default accelerator key. It
should be Command, and
- Issue 46807 - Cannot delete with the keyboard in explorer,
etc. DeleteAction is bound to the Delete key. Mac keyboards do
not have a Delete key.
- Issue 46808 - Command-G should be Find Next, not F3 (this
causes particular pain on mac laptops, where F3 is consumed by
the OS, and Fn-F3 must be pressed for this commonly used
action)
Changes needed to fix these issues:
- Support a "hidden" attribute on keybinding files in the system.
This will allow us to selectively bind a keystroke, i.e.
<attr name="hidden" methodvalue="some.class.isMac"/>
...
<attr name="hidden" methodvalue="some.class.isNotMac"/>
- Support "explicit" keybindings. The patch attached to issue
26854 extends keybinding files to allow them to prepend "X-" to
their filename, and modifies the conversion methods in Utilities
and the shortcuts editor to understand it. What this does:
- It allows the shortcuts editor to work - new shortcuts
entered by the user are marked as explicit, so if the user
enters the shortcut "Ctrl-[" it won't get blindly remapped to
"Command-[".
- It allows modules to register shortcuts that should use
Ctrl, even on the mac. For example, in issue 46808,
Command-G should be Find-Next, not F3, to fit the
mac guidelines and be consistent with other mac apps.
By making it an explicit mapping, GotoAction can still
be bound to Ctrl-G on the mac.
A patch for issue 26854 is available on that issue; I will attach
the patch to support the "hidden" attribute here.
Please, please, let's try to get this in for promo D.

Re. the 'hidden' attr - I would rather suggest that Mac-specific
keybindings be defined in a different layer, installed by some Mac
support module. More in keeping with the general usage of layers,
IMHO, and cleaner from the perspective of other modifications to the
shortcut list. So a provisional -1 from me on that part.
Tim I request this issue be split in half as it consists of two
entirely different change proposals and it is harder to track when
they are mixed together this way.

> I would rather suggest that Mac-specific
> keybindings be defined in a different layer, installed by some Mac
> support module.
I agree that would be nicer. AFAIK there is no way to include a module that is provisionally
installed, only on the mac. So while I agree with the sentiment, the first goal is to make
NetBeans 4.0 something that mac users will want to use.
Yes, a module with mac keybindings could be included only in the mac installer; this has
some down-sides:
- Someone who does a build on a mac is not testing exactly what will ship
- Anything that complicates the build/installer build process reduces the likelihood that it
will make it into 4.0
- It's another module that references classes it doesn't own (since it will refer to action
classes and files in core/ui's layer). That makes it much more likely to get broken, and
since we don't have that many people developing on macs, much less likely that the
breakage will be found.
> Tim I request this issue be split in half as it consists of two
> entirely different change proposals and it is harder to track when
> they are mixed together this way.
Well, either one is pretty useless without the other if the goal is to make NetBeans 4.0
something appealing to mac users.

Per Jesse's request, consider this issue split: supporting the "hidden" attribute on
ShortcutsFolder can be handled separately in issue 46806.
The requested compatibility contract level is "friend". We need to do something for this
for 4.0. Agreed that it would be preferable to have a new API for
- Registering both editor and system shortcuts in a similar way
- Allowing per-platform key mappings
but that we're not likely to have that in the 4.0 timeframe, but we do need to create a good
user experience for mac users, and the principal blocker is unnatural keyboard shortcuts
which are unlike other applications.

"there is no way to include a module that is provisionally installed,
only on the mac" - not true, actually, you can just have a module
which on startup turns itself off if it is not on a Mac. Will not work
in case you start a userdir on some other platform and then continue
using it on a Mac, though this is probably rare. Currently no way to
have a module check for enablement on each startup; issue #26338 would
provide essentially the same benefits. Not necessarily convenient in
this case however.

The partial problem with post-promoD is that I still hope that we will
be able to keep platform compatible for a while (next promo). Removing
any API however does break that hope.
So I suggest to do it in a better way. Let's have specific apple
shortcuts in applemenu module and let's disable it on other OSes using
the issue 46833.

<off-topic>
> I still hope that we will be able to keep platform compatible for a while (next promo)
Proper TTV integration (shares renderers w/ propsheet) will require splitting PropertyEnv
into a parent class in org.netbeans.modules.openide.explorer. Should we do it now?
</off topic>
We have a better proposal: Instead of X- to mark things explicit, we will use D in the
shortcut name to indicate that the default menu accelerator key for the platform should be
used. This will map to CTRL or META depending on the platform.
Once I've tested it some more, I will attach a new patch (which also patches many modules'
layer files to use the new designation).
Preferable?

Created attachment 16622[details]
Revised patch - includes Jarda's patch to conditionally enable modules only on one platform, now uses wildcard character for the default menu accel, converts all necessary keybindings in trunk to use it, moves hiding/modifying keybindings for apple to ap

New patch uses wildcard char, so, for example, DA-F5 resolves on mac to MA-F5 and on
pc to CA-F5; modifies the shortcuts editor to, when deleting/replacing, try both and any
possible orderings of the modifier characters (AFAICT this was broken before - if you
deleted MA-F5 but it was registered as AM-F5, it would come back after a restart).
Custom mac keybindings are moved to the applemenu module.

I cannot review the changes in editor/** that is up to Mila. Otherwise
I am fine with the changes. I require a test for Utilities to cover
the behaviour of "D" and a test for ShortcutsFolder to cover the
getPermutation method by replacing assigning new a shortcut that
forces existing one to be deleted. Then I'd like to remind that we
need to update the documentation as well.

I wouldn't call it a "wildcard" char, which would mean "any modifier
you like". It is a specific, single modifier, which varies strictly
with platform. Just a nit about terminology.
Please exclude Yarda's quite independent patch from your diff, it is
just confusing.
Is the following intentional?
- <file name="C-0.shadow">
+ <file name="C-D.shadow">
<attr name="originalFile"
stringvalue="Actions/Window/org-netbeans-core-windows-actions-SwitchToRecentDocumentAction.instance"/>
</file>
Note s/0/D/.
Should be consistent b/w o.o.u.Utilities and
o.n.editor.SettingsDefaults as to how Mac OS X is detected: os.name
vs. mrj.version?

Regarding editor changes we will also need to patch the keybindings
xml files so that the shortcuts diffs will be properly stored (the
duality of the editor keybindings entering is an unwanted relict from
previous versions). In fact we will need to do a similar change like
"C"->"D" for system keybindings declarative entering. I need to do
some more analysis so I will write more info tomorrow.

> Should be consistent b/w o.o.u.Utilities and
> o.n.editor.SettingsDefaults as to how Mac OS X is detected: os.name
> vs. mrj.version?
Last I knew, the editor lib was furiously trying to not have dependencies on org.openide.*.
If that is no longer true, of course, it would be better to use the same code everywhere,
but that's the reason I tested "mrj.version" in the editor lib.
Mila, if you could point out where the settings files are, or supply the necessary diff, I'd
appreciate it!

We need to patch the
editor/src/org/netbeans/modules/editor/resources/XMLs/DefaultGlobalKeyBindings.xml
and DefaultKeyBindings.xml in the same directory. Your patch seems to
override the o.o.u.Utilities.stringToKey() to which we also delegate
from our OptionUtilities.stringToKey() when reading the keystrokes
from XML file for diffing against the currently present keystrokes.
BTW I have entered editor issue 47294 to finally get rid of the
keystrokes specifications in the SettingsDefaults.

Mila, I've attached a new version of the patches. There is one discrepancy between the
settings XML files and the class SettingsDefaults: In SettingsDefaults, I conditionally set
find-next to be meta-G on the mac and F3 everywhere else, and conditionally set select-
next-word and friends to use ALT instead of CTRL, to be consistent with other mac
applications.
However, there is no way to do that in the XML files. We could rev the DTD and add an
optional attribute for such a thing; should we do that?
You said that the code in SettingsDefaults is actually duplicating what's in the XML file; I
don't totally understand how these settings files are used; in practice, what happens is the
code in SettingsDefaults.java wins. So I'll need some advice on what to do here - and
whenever you do get rid of SettingsDefaults, some way to set keys conditionally by
platform will need to be put in so this keeps working.

Well I still think that the best solution would be have a dedicated
xml file for the mac (and possibly other platforms too if necessary)
but that's probably not a short-term solution.
I've described how the editor's keybinding xml files are used (and
why we want to get rid of the SettingsDefaults) in the issue 47294.
Honestly I don't know how to properly solve the Meta-G versus F3
problem nicely. Wouldn't it be possible to have both F3 and Meta-G
keybindings defined for it? Not sure whether Alt is not interpreted as
Meta on some Unixes or other platforms though (it does not seem to be
on my RH9 Linux at least ;).
In the worst case we would have to patch the editor keybindings after
reading from the xml file so that F3 becomes Meta-G. It can be done
e.g. in KeyBindingsMIMEOptionFile at line 120.

Dedicated file on macosx? Pretty simple, just provide one in
ide/applemenu and make it override the default one provided by editor.
Afaik you need applemenu depend on editor to make sure the override
always take effect.

Binding both F3 and Meta-G is fine - won't cause a problem. But
select-next-word and friends should be ctrl on the PC and Alt on the
mac. Probably the parsing will just have to be patched for that, or
it needs to recognize some special token for "word select modifier"
which it can conditionally map to ctrl on the pc and alt on the mac.

Note - if the editor used separate files for each key binding, as core
does for global accelerators, there would be little risk of a few
Mac-specific bindings in ide/applemenu falling out of synch with
editor's defaults, since you would only need to override those you
want to change.

Okay, I'll attach another patch, which overrides the correct keybindings in its layer.
But I think keybinding support is either broken, or having a module supplying only the diff
of the available keybindings breaks it (Mila, in our conversation earlier, we concluded that
the applemenu module's settings XML file should be a diff of the original. But won't that
mean the original editor XML files are completely hidden by the file applemenu adds?).
I will test this on an unmodified build, and file separately if it is indeed broken. What
happens:
- Adding global keybindings works the first time you do it. They are written to the
userdir keybindings file.
- Removing global keybindings writes nothing to the userdir key bindings file
- After shutdown and restart, neither adding nor removing keybindings writes anything to
the userdir file
Probably in the case of bindings registered with D-whatever, it's looking for a binding M-
whatever, and not finding it (it will need to check the D- permutation and the M-
permutation on mac or C- permutation elsewhere).
Also for removing keybindings, it could simply only be seeing my layer-defined file from
applemenu, and not finding anything there to remove. Does the editor actually try to fetch
things from various layers? How is the merge done? (and where?)

Okay, I think I've got it all working and well behaved. Caveats:
- When applemenu actually declares a runtime-only dep on editor & core/windows, it
silently fails to install. Commented out for now and works without it, though that may be
luck.
- I've duplicated the "permutations" code in KeyBindingsMIMEOptionFile. This code
already has unit tests for the copy in core, as part of the patch. I'm starting to think it
might be better to:
- Rather than duplicate this code, have a new Utilities method like:
public Iterator getPermutations (String keystring);
which anyone who was trying to map a given keystroke to a declaratively registered
string should use - Utilities.keyToString() doesn't declare ordering, but
Utilities.stringToKey() returns only one order. So it's always been true that if you
registered SA-Y, keyToString would return AS-Y and you'd find no match.
If we think we'll really, soon, redesign all our keyboard shortcut handling, we
probably shouldn't bother, as one more layer of indirection would solve this.

Just a note for those of you who are watching this
issue with an eye to a usable netbeans on osX, these
changes didn't make it into 4.0 beta 2, so you'll
have to wait a bit longer.
more info at http://weblogs.java.net/pub/wlg/1830