diff --git a/platform/platform-api/resources/messages/KeyMapBundle.properties b/platform/platform-api/resources/messages/KeyMapBundle.properties index 6edd1cac9392..e31f40c7ee21 100644 --- a/platform/platform-api/resources/messages/KeyMapBundle.properties +++ b/platform/platform-api/resources/messages/KeyMapBundle.properties @@ -41,7 +41,8 @@ add.keymap.label=A&dd remove.keymap.label=Remo&ve unnamed.list.display.name=unnamed -prefer.key.position=Prefer key position over key char with national layout +use.national.layouts.for.shortcuts=Use national layouts for shortcuts +use.us.non.alpha.num.keys=Use US non alpha numerical keys for shortcuts disable.mnemonic.in.menu.check.box=Disable mnemonics in &menu add.keyboard.shortcut.button=Add &Keyboard Shortcut... diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java deleted file mode 100644 index 38fff570019a..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/keymap/KeyboardSettingsExternalizable.java +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.openapi.keymap; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import org.cef.OS; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; -import java.awt.im.InputContext; -import java.util.Locale; - -/** - * @author Denis Fokin - */ - -@State(name = "KeyboardSettings", storages = @Storage("keyboard.xml")) -public class KeyboardSettingsExternalizable implements PersistentStateComponent { - - private static final String [] supportedNonEnglishLanguages = {"de", "fr", "it", "uk"}; - public static final String VMOption = "com.sun.awt.use.national.layouts"; - - public static boolean isSupportedKeyboardLayout(@NotNull Component component) { - String keyboardLayoutLanguage = getLanguageForComponent(component); - for (String language : supportedNonEnglishLanguages) { - if (language.equals(keyboardLayoutLanguage)) { - return true; - } - } - // linux have poor support of locales so lets show this option every on linux system - return OS.isLinux(); - } - - @Nullable - public static String getLanguageForComponent(@NotNull Component component) { - final Locale locale = getLocaleForComponent(component); - return locale == null ? null : locale.getLanguage(); - } - - @Nullable - protected static Locale getLocaleForComponent(@NotNull Component component) { - final InputContext context = component.getInputContext(); - return context == null ? null : context.getLocale(); - } - - @Nullable - public static String getDisplayLanguageNameForComponent(@NotNull Component component) { - final Locale locale = getLocaleForComponent(component); - return locale == null ? null : locale.getDisplayLanguage(); - } - - public static final class OptionSet { - public boolean PREFER_KEY_POSITION_OVER_CHAR_OPTION - = "true".equals(System.getProperty("com.jetbrains.use.old.keyevent.processing")); - } - - private OptionSet myOptions = new OptionSet(); - - public static KeyboardSettingsExternalizable getInstance() { - if (ApplicationManager.getApplication().isDisposed()) { - return new KeyboardSettingsExternalizable(); - } - else { - return ServiceManager.getService(KeyboardSettingsExternalizable.class); - } - } - - @Nullable - @Override - public OptionSet getState() { - return myOptions; - } - - @Override - public void loadState(@NotNull OptionSet state) { - state.PREFER_KEY_POSITION_OVER_CHAR_OPTION - = state.PREFER_KEY_POSITION_OVER_CHAR_OPTION - || "true".equals(System.getProperty("com.jetbrains.use.old.keyevent.processing")); - - myOptions = state; - } - - public boolean isPreferKeyPositionOverCharOption () { - return myOptions.PREFER_KEY_POSITION_OVER_CHAR_OPTION; - } - - public void setPreferKeyPositionOverCharOption (boolean enabled) { - myOptions.PREFER_KEY_POSITION_OVER_CHAR_OPTION = enabled; - } - -} diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/NationalKeyboardSupport.java b/platform/platform-api/src/com/intellij/openapi/keymap/NationalKeyboardSupport.java new file mode 100644 index 000000000000..295a1e801fce --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/keymap/NationalKeyboardSupport.java @@ -0,0 +1,123 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.keymap; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.awt.im.InputContext; +import java.util.Locale; + + +@State(name = "KeyboardSettings", storages = @Storage("keyboard.xml")) +public class NationalKeyboardSupport implements PersistentStateComponent { + private static final String[] MAC_SUPPORTED_LOCALES = {"de", "fr", "it", "no"}; + private static final String[] WIN_SUPPORTED_LOCALES = {"be", "ru", "uk", "bg", "sr"}; + + public static final String VMOption = getVMOption(); + + public static boolean isSupportedKeyboardLayout(@NotNull Component component) { + if (SystemInfo.isLinux) { + return true; + } + + String[] supportedNonEnglishLanguages; + if (SystemInfo.isMac) { + supportedNonEnglishLanguages = MAC_SUPPORTED_LOCALES; + } + else if (SystemInfo.isWindows) { + supportedNonEnglishLanguages = WIN_SUPPORTED_LOCALES; + } + else { + return false; + } + + String keyboardLayoutLanguage = getLanguageForComponent(component); + for (String language : supportedNonEnglishLanguages) { + if (language.equals(keyboardLayoutLanguage)) { + return true; + } + } + return false; + } + + public static @NotNull String getVMOption() { + if (SystemInfo.isMac || SystemInfo.isLinux) { + return "com.sun.awt.use.national.layouts"; + } + return "com.sun.awt.useLatinNonAlphaNumKeycodes"; + } + + public static @NotNull String getKeymapBundleKey() { + if (SystemInfo.isMac || SystemInfo.isLinux) { + return "use.national.layouts.for.shortcuts"; + } + return "use.us.non.alpha.num.keys"; + } + + + @Nullable + public static String getLanguageForComponent(@NotNull Component component) { + final Locale locale = getLocaleForComponent(component); + return locale == null ? null : locale.getLanguage(); + } + + @Nullable + protected static Locale getLocaleForComponent(@NotNull Component component) { + final InputContext context = component.getInputContext(); + return context == null ? null : context.getLocale(); + } + + public static final class OptionSet { + public boolean enabled = "true".equals(System.getProperty(VMOption)); + } + + private OptionSet myOptions = new OptionSet(); + + public static NationalKeyboardSupport getInstance() { + if (ApplicationManager.getApplication().isDisposed()) { + return new NationalKeyboardSupport(); + } + else { + return ServiceManager.getService(NationalKeyboardSupport.class); + } + } + + @Nullable + @Override + public OptionSet getState() { + return myOptions; + } + + @Override + public void loadState(@NotNull OptionSet state) { + state.enabled + = state.enabled || "true".equals(System.getProperty(VMOption)); + + myOptions = state; + } + + @Override + public void noStateLoaded() { + // on MacOS national keymap support is turned on by default + if (SystemInfo.isMac) { + myOptions.enabled = "true".equals(System.getProperty(VMOption, "true")); + } + } + + public boolean getEnabled() { + return myOptions.enabled; + } + + public void setEnabled(boolean enabled) { + myOptions.enabled = enabled; + } +} + + diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/KeyboardInternationalizationNotificationManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/KeyboardInternationalizationNotificationManager.java deleted file mode 100644 index b181295b432e..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/KeyboardInternationalizationNotificationManager.java +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.openapi.editor.impl; - -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationDisplayType; -import com.intellij.notification.NotificationListener; -import com.intellij.notification.NotificationsConfiguration; -import com.intellij.openapi.keymap.KeyboardSettingsExternalizable; -import com.intellij.openapi.keymap.impl.ui.KeymapPanel; -import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.ex.WindowManagerEx; -import org.jetbrains.annotations.NotNull; - -import javax.swing.event.HyperlinkEvent; - -/** - * @author Denis Fokin - */ -public final class KeyboardInternationalizationNotificationManager { - public static final String LOCALIZATION_GROUP_DISPLAY_ID = "Localization and Internationalization"; - public static boolean notificationHasBeenShown; - - private KeyboardInternationalizationNotificationManager() { - } - -/* public static void showNotification() { - - Window mostRecentFocusedWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow(); - if (notificationHasBeenShown || (mostRecentFocusedWindow != null && !KeyboardSettingsExternalizable.isSupportedKeyboardLayout(mostRecentFocusedWindow))) return; - - MyNotificationListener listener = - new MyNotificationListener(); - - Notifications.Bus.notify(createNotification(LOCALIZATION_GROUP_DISPLAY_ID, listener)); - notificationHasBeenShown = true; - }*/ - -/* public static Notification createNotification(@NotNull final String groupDisplayId, @Nullable NotificationListener listener) { - - Window recentFocusedWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow(); - - if (recentFocusedWindow == null) { - recentFocusedWindow = Window.getWindows()[0]; - } - - final String productName = ApplicationNamesInfo.getInstance().getProductName(); - - String text = - "We have found out that you are using a non-english keyboard layout. You can enable smart layout support for " + - KeyboardSettingsExternalizable.getDisplayLanguageNameForComponent(recentFocusedWindow) + " language." + - "You can change this option in the settings of " + productName + " more..."; - - String title = "Enable smart keyboard internationalization for " + productName + "."; - - return new Notification(groupDisplayId, title, - text, - NotificationType.INFORMATION, - listener); - }*/ - - private static class MyNotificationListener implements NotificationListener { - - MyNotificationListener() { - } - - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - final String description = event.getDescription(); - if ("enable".equals(description)) { - KeyboardSettingsExternalizable.getInstance().setPreferKeyPositionOverCharOption(true); - } - else if ("settings".equals(description)) { - final ShowSettingsUtil util = ShowSettingsUtil.getInstance(); - IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null); - //util.editConfigurable((JFrame)ideFrame, new StatisticsConfigurable(true)); - util.showSettingsDialog(ideFrame.getProject(), KeymapPanel.class); - } - - NotificationsConfiguration.getNotificationsConfiguration().changeSettings(LOCALIZATION_GROUP_DISPLAY_ID, NotificationDisplayType.NONE, false, false); - notification.expire(); - } - } - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index 0bf371a378d3..a1529acef2f8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -68,7 +68,7 @@ import java.util.Map; import static com.intellij.openapi.actionSystem.impl.ActionToolbarImpl.updateAllToolbarsImmediately; public class KeymapPanel extends JPanel implements SearchableConfigurable, Configurable.NoScroll, KeymapListener, Disposable { - private JCheckBox preferKeyPositionOverCharOption; + private JCheckBox nationalKeyboardsSupport; private final KeymapSelector myKeymapSelector = new KeymapSelector(this::currentKeymapChanged); private final KeymapSchemeManager myManager = myKeymapSelector.getManager(); @@ -96,21 +96,23 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi keymapPanel.add(createKeymapSettingsPanel(), BorderLayout.CENTER); IdeFrame ideFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame(); - if (ideFrame != null && KeyboardSettingsExternalizable.isSupportedKeyboardLayout(ideFrame.getComponent())) { - preferKeyPositionOverCharOption = new JCheckBox(new AbstractAction(KeyMapBundle.message("prefer.key.position")) { - @Override - public void actionPerformed(ActionEvent e) { - KeyboardSettingsExternalizable.getInstance().setPreferKeyPositionOverCharOption(preferKeyPositionOverCharOption.isSelected()); - VMOptions.writeOption(KeyboardSettingsExternalizable.VMOption, "=", - Boolean.toString(!KeyboardSettingsExternalizable.getInstance().isPreferKeyPositionOverCharOption())); - ApplicationManager.getApplication().invokeLater( - () -> ApplicationManager.getApplication().restart(), - ModalityState.NON_MODAL - ); - } - }); - preferKeyPositionOverCharOption.setBorder(JBUI.Borders.empty()); - keymapPanel.add(preferKeyPositionOverCharOption, BorderLayout.SOUTH); + if (ideFrame != null && NationalKeyboardSupport.isSupportedKeyboardLayout(ideFrame.getComponent())) { + nationalKeyboardsSupport = new JCheckBox( + new AbstractAction(KeyMapBundle.message(NationalKeyboardSupport.getKeymapBundleKey())) { + @Override + public void actionPerformed(ActionEvent e) { + NationalKeyboardSupport.getInstance().setEnabled(nationalKeyboardsSupport.isSelected()); + VMOptions.writeOption(NationalKeyboardSupport.getVMOption(), "=", + Boolean.toString(NationalKeyboardSupport.getInstance().getEnabled())); + ApplicationManager.getApplication().invokeLater( + () -> ApplicationManager.getApplication().restart(), + ModalityState.NON_MODAL + ); + } + }); + nationalKeyboardsSupport.setSelected(NationalKeyboardSupport.getInstance().getEnabled()); + nationalKeyboardsSupport.setBorder(JBUI.Borders.empty()); + keymapPanel.add(nationalKeyboardsSupport, BorderLayout.SOUTH); } add(keymapPanel, BorderLayout.CENTER); @@ -555,8 +557,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi @Override public void reset() { - if (preferKeyPositionOverCharOption != null) { - preferKeyPositionOverCharOption.setSelected(KeyboardSettingsExternalizable.getInstance().isPreferKeyPositionOverCharOption()); + if (nationalKeyboardsSupport != null) { + nationalKeyboardsSupport.setSelected(NationalKeyboardSupport.getInstance().getEnabled()); } myManager.reset(); } diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index ec63ac6334d7..f7d962f72cd0 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -543,7 +543,7 @@ /> - +