8155030: The Menu Mnemonics are always displayed for GTK LAF

Hides mnemonics on menus, buttons, and labels for GTK L&F.

Moved shared code for hiding mnemonics into
sun/swing/MnemonicHandler and AltProcessor to avoid code duplication.

Reviewed-by: prr, tr, achung, dnguyen, aivanov
This commit is contained in:
Abhishek Kumar 2024-07-12 12:37:58 +00:00
parent 559826c292
commit 2fc7eb44a0
19 changed files with 431 additions and 242 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -75,6 +75,7 @@ import com.apple.laf.AquaButtonExtendedTypes.TypeSpecifier;
import com.apple.laf.AquaUtilControlSize.Sizeable;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
public class AquaButtonUI extends BasicButtonUI implements Sizeable {
@ -487,12 +488,10 @@ public class AquaButtonUI extends BasicButtonUI implements Sizeable {
* Use the paintText method which takes the AbstractButton argument.
*/
protected void paintText(final Graphics g, final JComponent c, final Rectangle localTextRect, final String text) {
final Graphics2D g2d = g instanceof Graphics2D ? (Graphics2D)g : null;
final AbstractButton b = (AbstractButton)c;
final ButtonModel model = b.getModel();
final FontMetrics fm = g.getFontMetrics();
final int mnemonicIndex = AquaMnemonicHandler.isMnemonicHidden() ? -1 : b.getDisplayedMnemonicIndex();
final int mnemonicIndex = MnemonicHandler.isMnemonicHidden() ? -1 : b.getDisplayedMnemonicIndex();
/* Draw the Text */
if (model.isEnabled()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,16 +25,19 @@
package com.apple.laf;
import java.awt.*;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import sun.swing.SwingUtilities2;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicLabelUI;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
public class AquaLabelUI extends BasicLabelUI {
private static final RecyclableSingleton<AquaLabelUI> aquaLabelUI = new RecyclableSingletonFromDefaultConstructor<AquaLabelUI>(AquaLabelUI.class);
@ -55,7 +58,7 @@ public class AquaLabelUI extends BasicLabelUI {
protected void paintEnabledText(final JLabel l, final Graphics g, final String s, final int textX, final int textY) {
int mnemIndex = l.getDisplayedMnemonicIndex();
if (AquaMnemonicHandler.isMnemonicHidden()) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemIndex = -1;
}
@ -72,7 +75,7 @@ public class AquaLabelUI extends BasicLabelUI {
*/
protected void paintDisabledText(final JLabel l, final Graphics g, final String s, final int textX, final int textY) {
int accChar = l.getDisplayedMnemonicIndex();
if (AquaMnemonicHandler.isMnemonicHidden()) {
if (MnemonicHandler.isMnemonicHidden()) {
accChar = -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,6 +55,8 @@ import javax.swing.plaf.basic.BasicLookAndFeel;
import apple.laf.JRSUIControl;
import apple.laf.JRSUIUtils;
import sun.swing.AltProcessor;
import sun.swing.MnemonicHandler;
import sun.swing.SwingAccessor;
import sun.swing.SwingUtilities2;
@ -174,7 +176,9 @@ public class AquaLookAndFeel extends BasicLookAndFeel {
spf.setActive(true);
PopupFactory.setSharedInstance(spf);
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(AquaMnemonicHandler.getInstance());
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventPostProcessor(AltProcessor.getInstance());
MnemonicHandler.setMnemonicHidden(true);
}
/**
@ -185,7 +189,8 @@ public class AquaLookAndFeel extends BasicLookAndFeel {
* @see #initialize
*/
public void uninitialize() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(AquaMnemonicHandler.getInstance());
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removeKeyEventPostProcessor(AltProcessor.getInstance());
final PopupFactory popupFactory = PopupFactory.getSharedInstance();
if (popupFactory instanceof ScreenPopupFactory spf) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,21 +25,39 @@
package com.apple.laf;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import sun.swing.SwingUtilities2;
import apple.laf.JRSUIConstants.*;
import apple.laf.JRSUIConstants.State;
import apple.laf.JRSUIConstants.Widget;
import com.apple.laf.AquaIcon.InvertableIcon;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
/**
* AquaMenuPainter, implements paintMenuItem to avoid code duplication
@ -287,7 +305,7 @@ public class AquaMenuPainter {
if (v != null) {
v.paint(g, textRect);
} else {
final int mnemonic = (AquaMnemonicHandler.isMnemonicHidden() ? -1 : model.getMnemonic());
final int mnemonic = (MnemonicHandler.isMnemonicHidden() ? -1 : model.getMnemonic());
drawString(g, c, text, mnemonic, textRect.x, textRect.y + fm.getAscent(), isEnabled, isSelected);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,12 +24,19 @@
*/
package com.sun.java.swing.plaf.gtk;
import javax.swing.*;
import javax.swing.plaf.synth.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.JComponent;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthGraphicsUtils;
import sun.swing.MnemonicHandler;
/**
* @author Joshua Outwater
*/
@ -49,6 +56,11 @@ class GTKGraphicsUtils extends SynthGraphicsUtils {
int componentState = context.getComponentState();
String themeName = GTKLookAndFeel.getGtkThemeName();
if (MnemonicHandler.isMnemonicHidden()) {
mnemonicIndex = -1;
}
if (themeName != null && themeName.startsWith("blueprint") &&
shouldShadowText(context.getRegion(), componentState)) {
@ -115,7 +127,8 @@ class GTKGraphicsUtils extends SynthGraphicsUtils {
g.setColor(color);
}
}
super.paintText(context, g, text, bounds, mnemonicIndex);
super.paintText(context, g, text, bounds,
MnemonicHandler.isMnemonicHidden() ? -1 : mnemonicIndex);
}
private static boolean shouldShadowText(Region id, int state) {

View File

@ -25,28 +25,50 @@
package com.sun.java.swing.plaf.gtk;
import java.awt.*;
import java.beans.*;
import java.io.File;
import java.lang.ref.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.Window;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import javax.swing.*;
import javax.swing.colorchooser.*;
import javax.swing.plaf.*;
import javax.swing.plaf.synth.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.LayoutStyle;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.plaf.BorderUIResource;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.DimensionUIResource;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthLookAndFeel;
import javax.swing.plaf.synth.SynthStyleFactory;
import javax.swing.text.DefaultEditorKit;
import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType;
import com.sun.java.swing.plaf.gtk.GTKConstants.StateType;
import java.util.HashMap;
import java.util.Map;
import sun.awt.SunToolkit;
import sun.awt.UNIXToolkit;
import sun.awt.OSInfo;
import sun.security.action.GetPropertyAction;
import sun.swing.AltProcessor;
import sun.swing.DefaultLayoutStyle;
import sun.swing.MnemonicHandler;
import sun.swing.SwingAccessor;
import sun.swing.SwingUtilities2;
@ -866,7 +888,6 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
"ctrl released ENTER", "release"
},
"ScrollBar.squareButtons", Boolean.FALSE,
"ScrollBar.thumbHeight", Integer.valueOf(14),
"ScrollBar.width", Integer.valueOf(16),
@ -1414,6 +1435,10 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
return c.getComponentOrientation().isLeftToRight();
}
/**
* {@inheritDoc}
*/
@Override
public void initialize() {
/*
* We need to call loadGTK() to ensure that the native GTK
@ -1456,6 +1481,23 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
gtkAAFontSettingsCond = SwingUtilities2.isLocalDisplay();
aaTextInfo = new HashMap<>(2);
SwingUtilities2.putAATextInfo(gtkAAFontSettingsCond, aaTextInfo);
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventPostProcessor(AltProcessor.getInstance());
// By default mnemonics are hidden for GTK L&F
MnemonicHandler.setMnemonicHidden(true);
}
/**
* {@inheritDoc}
*/
@Override
public void uninitialize() {
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.removeKeyEventPostProcessor(AltProcessor.getInstance());
MnemonicHandler.setMnemonicHidden(false);
super.uninitialize();
}
static ReferenceQueue<GTKLookAndFeel> queue = new ReferenceQueue<GTKLookAndFeel>();

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.swing;
import java.awt.KeyEventPostProcessor;
import java.awt.Window;
import java.awt.event.KeyEvent;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
public final class AltProcessor implements KeyEventPostProcessor {
private AltProcessor() {}
private static final AltProcessor altProcessor = new AltProcessor();
public static KeyEventPostProcessor getInstance() {
return altProcessor;
}
@Override
public boolean postProcessKeyEvent(final KeyEvent ev) {
if (ev.getKeyCode() != KeyEvent.VK_ALT) {
return false;
}
final JRootPane root = SwingUtilities.getRootPane(ev.getComponent());
final Window winAncestor = (root == null ? null : SwingUtilities.getWindowAncestor(root));
switch (ev.getID()) {
case KeyEvent.KEY_PRESSED:
MnemonicHandler.setMnemonicHidden(false);
break;
case KeyEvent.KEY_RELEASED:
MnemonicHandler.setMnemonicHidden(true);
break;
}
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
return false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,24 +23,44 @@
* questions.
*/
package com.apple.laf;
package sun.swing;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import javax.swing.*;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.UIManager;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public final class MnemonicHandler {
public class AquaMnemonicHandler {
private static final RecyclableSingleton<AltProcessor> altProcessor = new RecyclableSingletonFromDefaultConstructor<AltProcessor>(AltProcessor.class);
public static KeyEventPostProcessor getInstance() {
return altProcessor.get();
private static boolean isMnemonicHidden;
private MnemonicHandler() {}
/**
* Gets the state of the hide mnemonic flag.
* This only has meaning if this feature is supported by the underlying OS.
*
* @return true if mnemonics are hidden, otherwise, false
*/
public static boolean isMnemonicHidden() {
if (UIManager.getBoolean("Button.showMnemonics")) {
// Do not hide mnemonics if the UI defaults do not support this
isMnemonicHidden = false;
}
return isMnemonicHidden;
}
protected static boolean isMnemonicHidden = true; // true by default
/**
* Sets the state of the hide mnemonic flag. This flag is used by the
* component UI delegates to determine if the mnemonic should be rendered.
* This method is a non operation if the underlying operating system
* does not support the mnemonic hiding feature.
*
* @param hide true if mnemonics should be hidden
*/
public static void setMnemonicHidden(final boolean hide) {
if (UIManager.getBoolean("Button.showMnemonics")) {
// Do not hide mnemonics if the UI defaults do not support this
@ -51,48 +71,9 @@ public class AquaMnemonicHandler {
}
/**
* Gets the state of the hide mnemonic flag. This only has meaning if this feature is supported by the underlying OS.
*
* @return true if mnemonics are hidden, otherwise, false
* @see #setMnemonicHidden
* @since 1.4
*/
public static boolean isMnemonicHidden() {
if (UIManager.getBoolean("Button.showMnemonics")) {
// Do not hide mnemonics if the UI defaults do not support this
isMnemonicHidden = false;
}
return isMnemonicHidden;
}
static class AltProcessor implements KeyEventPostProcessor {
public boolean postProcessKeyEvent(final KeyEvent ev) {
if (ev.getKeyCode() != KeyEvent.VK_ALT) {
return false;
}
final JRootPane root = SwingUtilities.getRootPane(ev.getComponent());
final Window winAncestor = (root == null ? null : SwingUtilities.getWindowAncestor(root));
switch(ev.getID()) {
case KeyEvent.KEY_PRESSED:
setMnemonicHidden(false);
break;
case KeyEvent.KEY_RELEASED:
setMnemonicHidden(true);
break;
}
repaintMnemonicsInWindow(winAncestor);
return false;
}
}
/*
* Repaints all the components with the mnemonics in the given window and all its owned windows.
*/
static void repaintMnemonicsInWindow(final Window w) {
public static void repaintMnemonicsInWindow(final Window w) {
if (w == null || !w.isShowing()) {
return;
}
@ -105,29 +86,22 @@ public class AquaMnemonicHandler {
repaintMnemonicsInContainer(w);
}
/*
/**
* Repaints all the components with the mnemonics in container.
* Recursively searches for all the subcomponents.
*/
static void repaintMnemonicsInContainer(final Container cont) {
for (int i = 0; i < cont.getComponentCount(); i++) {
final Component c = cont.getComponent(i);
private static void repaintMnemonicsInContainer(final Container cont) {
final Component[] elements = cont.getComponents();
for (final Component c : elements) {
if (c == null || !c.isVisible()) {
continue;
}
if (c instanceof AbstractButton && ((AbstractButton)c).getMnemonic() != '\0') {
if ((c instanceof AbstractButton b && b.getMnemonic() != '\0')
|| (c instanceof JLabel l && l.getDisplayedMnemonic() != '\0')) {
c.repaint();
continue;
}
if (c instanceof JLabel && ((JLabel)c).getDisplayedMnemonic() != '\0') {
c.repaint();
continue;
}
if (c instanceof Container) {
repaintMnemonicsInContainer((Container)c);
} else if (c instanceof Container) {
repaintMnemonicsInContainer((Container) c);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,14 +25,31 @@
package com.sun.java.swing.plaf.windows;
import sun.swing.SwingUtilities2;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.*;
import javax.swing.*;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButton;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.plaf.UIResource;
import static com.sun.java.swing.plaf.windows.TMSchema.*;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
import static com.sun.java.swing.plaf.windows.TMSchema.Part;
import static com.sun.java.swing.plaf.windows.TMSchema.Prop;
import static com.sun.java.swing.plaf.windows.TMSchema.State;
import static com.sun.java.swing.plaf.windows.TMSchema.TypeEnum;
/**
* A collection of static utility methods used for rendering the Windows look
@ -60,7 +77,7 @@ public class WindowsGraphicsUtils {
int mnemIndex = b.getDisplayedMnemonicIndex();
// W2K Feature: Check to see if the Underscore should be rendered.
if (WindowsLookAndFeel.isMnemonicHidden() == true) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemIndex = -1;
}
@ -191,46 +208,4 @@ public class WindowsGraphicsUtils {
return c.getComponentOrientation().isLeftToRight();
}
/*
* Repaints all the components with the mnemonics in the given window and
* all its owned windows.
*/
static void repaintMnemonicsInWindow(Window w) {
if(w == null || !w.isShowing()) {
return;
}
Window[] ownedWindows = w.getOwnedWindows();
for(int i=0;i<ownedWindows.length;i++) {
repaintMnemonicsInWindow(ownedWindows[i]);
}
repaintMnemonicsInContainer(w);
}
/*
* Repaints all the components with the mnemonics in container.
* Recursively searches for all the subcomponents.
*/
static void repaintMnemonicsInContainer(Container cont) {
Component c;
for(int i=0; i<cont.getComponentCount(); i++) {
c = cont.getComponent(i);
if(c == null || !c.isVisible()) {
continue;
}
if(c instanceof AbstractButton
&& ((AbstractButton)c).getMnemonic() != '\0') {
c.repaint();
continue;
} else if(c instanceof JLabel
&& ((JLabel)c).getDisplayedMnemonic() != '\0') {
c.repaint();
continue;
}
if(c instanceof Container) {
repaintMnemonicsInContainer((Container)c);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicLabelUI;
import sun.awt.AppContext;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
/**
@ -62,7 +63,7 @@ public class WindowsLabelUI extends BasicLabelUI {
int textX, int textY) {
int mnemonicIndex = l.getDisplayedMnemonicIndex();
// W2K Feature: Check to see if the Underscore should be rendered.
if (WindowsLookAndFeel.isMnemonicHidden() == true) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemonicIndex = -1;
}
@ -75,7 +76,7 @@ public class WindowsLabelUI extends BasicLabelUI {
int textX, int textY) {
int mnemonicIndex = l.getDisplayedMnemonicIndex();
// W2K Feature: Check to see if the Underscore should be rendered.
if (WindowsLookAndFeel.isMnemonicHidden() == true) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemonicIndex = -1;
}
if ( UIManager.getColor("Label.disabledForeground") instanceof Color &&

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -93,6 +93,7 @@ import sun.font.FontUtilities;
import sun.security.action.GetPropertyAction;
import sun.swing.DefaultLayoutStyle;
import sun.swing.ImageIconUIResource;
import sun.swing.MnemonicHandler;
import sun.swing.StringUIClientPropertyKey;
import sun.swing.SwingAccessor;
import sun.swing.SwingUtilities2;
@ -196,6 +197,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel
}
KeyboardFocusManager.getCurrentKeyboardFocusManager().
addKeyEventPostProcessor(WindowsRootPaneUI.altProcessor);
MnemonicHandler.setMnemonicHidden(true);
}
@ -1908,48 +1910,10 @@ public class WindowsLookAndFeel extends BasicLookAndFeel
WindowsDesktopProperty.flushUnreferencedProperties();
}
// Toggle flag for drawing the mnemonic state
private static boolean isMnemonicHidden = true;
// Flag which indicates that the Win98/Win2k/WinME features
// should be disabled.
private static boolean isClassicWindows = false;
/**
* Sets the state of the hide mnemonic flag. This flag is used by the
* component UI delegates to determine if the mnemonic should be rendered.
* This method is a non operation if the underlying operating system
* does not support the mnemonic hiding feature.
*
* @param hide true if mnemonics should be hidden
* @since 1.4
*/
public static void setMnemonicHidden(boolean hide) {
if (UIManager.getBoolean("Button.showMnemonics") == true) {
// Do not hide mnemonics if the UI defaults do not support this
isMnemonicHidden = false;
} else {
isMnemonicHidden = hide;
}
}
/**
* Gets the state of the hide mnemonic flag. This only has meaning
* if this feature is supported by the underlying OS.
*
* @return true if mnemonics are hidden, otherwise, false
* @see #setMnemonicHidden
* @since 1.4
*/
public static boolean isMnemonicHidden() {
if (UIManager.getBoolean("Button.showMnemonics") == true) {
// Do not hide mnemonics if the UI defaults do not support this
isMnemonicHidden = false;
}
return isMnemonicHidden;
}
/**
* Gets the state of the flag which indicates if the old Windows
* look and feel should be rendered. This flag is used by the

View File

@ -52,6 +52,8 @@ import com.sun.java.swing.plaf.windows.TMSchema.Part;
import com.sun.java.swing.plaf.windows.TMSchema.State;
import com.sun.java.swing.plaf.windows.XPStyle.Skin;
import sun.swing.MnemonicHandler;
/**
* Windows rendition of the component.
*/
@ -149,11 +151,11 @@ public class WindowsMenuBarUI extends BasicMenuBarUI
MenuElement[] selectedPath = msm.getSelectedPath();
if (selectedPath.length > 0 && (selectedPath[0] instanceof JMenuBar)) {
msm.clearSelectedPath();
WindowsLookAndFeel.setMnemonicHidden(true);
MnemonicHandler.setMnemonicHidden(true);
} else {
MenuElement[] path = {menuBar, menu};
msm.setSelectedPath(path);
WindowsLookAndFeel.setMnemonicHidden(false);
MnemonicHandler.setMnemonicHidden(false);
}
WindowsLookAndFeel.repaintRootPane(menuBar);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,6 +46,7 @@ import com.sun.java.swing.plaf.windows.TMSchema.State;
import com.sun.java.swing.plaf.windows.XPStyle.Skin;
import sun.swing.MenuItemCheckIconFactory;
import sun.swing.MenuItemLayoutHelper;
import sun.swing.MnemonicHandler;
import sun.swing.SwingUtilities2;
/**
@ -203,7 +204,7 @@ public class WindowsMenuItemUI extends BasicMenuItemUI {
FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g);
int mnemIndex = menuItem.getDisplayedMnemonicIndex();
// W2K Feature: Check to see if the Underscore should be rendered.
if (WindowsLookAndFeel.isMnemonicHidden() == true) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemIndex = -1;
}
WindowsGraphicsUtils.paintXPText(menuItem,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicPopupMenuUI;
import com.sun.java.swing.plaf.windows.TMSchema.Part;
import com.sun.java.swing.plaf.windows.TMSchema.State;
import com.sun.java.swing.plaf.windows.XPStyle.Skin;
import sun.swing.MnemonicHandler;
import sun.swing.StringUIClientPropertyKey;
import static sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET;
@ -99,13 +100,13 @@ public class WindowsPopupMenuUI extends BasicPopupMenuUI {
MenuSelectionManager msm = (MenuSelectionManager)ev.getSource();
MenuElement[] path = msm.getSelectedPath();
if (path.length == 0) {
if(!WindowsLookAndFeel.isMnemonicHidden()) {
if (!MnemonicHandler.isMnemonicHidden()) {
// menu was canceled -- hide mnemonics
WindowsLookAndFeel.setMnemonicHidden(true);
MnemonicHandler.setMnemonicHidden(true);
if (repaintRoot != null) {
Window win =
SwingUtilities.getWindowAncestor(repaintRoot);
WindowsGraphicsUtils.repaintMnemonicsInWindow(win);
MnemonicHandler.repaintMnemonicsInWindow(win);
}
}
repaintRoot = null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -61,6 +61,8 @@ import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.basic.BasicRootPaneUI;
import javax.swing.plaf.basic.ComboPopup;
import sun.swing.MnemonicHandler;
/**
* Windows implementation of RootPaneUI, there is one shared between all
* JRootPane instances.
@ -93,13 +95,13 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
ev.consume();
} else if(path.length > 0) { // We are in ComboBox
menuCanceledOnPress = false;
WindowsLookAndFeel.setMnemonicHidden(false);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
MnemonicHandler.setMnemonicHidden(false);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
ev.consume();
} else {
menuCanceledOnPress = false;
WindowsLookAndFeel.setMnemonicHidden(false);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
MnemonicHandler.setMnemonicHidden(false);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
JMenuBar mbar = root != null ? root.getJMenuBar() : null;
if(mbar == null && winAncestor instanceof JFrame) {
mbar = ((JFrame)winAncestor).getJMenuBar();
@ -113,8 +115,8 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
void altReleased(KeyEvent ev) {
if (menuCanceledOnPress) {
WindowsLookAndFeel.setMnemonicHidden(true);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
MnemonicHandler.setMnemonicHidden(true);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
return;
}
@ -151,14 +153,14 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
path[0] = mbar;
path[1] = menu;
msm.setSelectedPath(path);
} else if(!WindowsLookAndFeel.isMnemonicHidden()) {
WindowsLookAndFeel.setMnemonicHidden(true);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
} else if (!MnemonicHandler.isMnemonicHidden()) {
MnemonicHandler.setMnemonicHidden(true);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
}
} else {
if((msm.getSelectedPath())[0] instanceof ComboPopup) {
WindowsLookAndFeel.setMnemonicHidden(true);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
MnemonicHandler.setMnemonicHidden(true);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
}
}
@ -193,8 +195,8 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
MenuSelectionManager.defaultManager();
MenuElement[] path = msm.getSelectedPath();
if (path.length <= 0) {
WindowsLookAndFeel.setMnemonicHidden(true);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
MnemonicHandler.setMnemonicHidden(true);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
}
}
altKeyPressed = false;
@ -202,9 +204,9 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
root = null;
winAncestor = null;
} else {
if (WindowsLookAndFeel.isMnemonicHidden() && ev.isAltDown()) {
WindowsLookAndFeel.setMnemonicHidden(false);
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
if (MnemonicHandler.isMnemonicHidden() && ev.isAltDown()) {
MnemonicHandler.setMnemonicHidden(false);
MnemonicHandler.repaintMnemonicsInWindow(winAncestor);
}
altKeyPressed = false;
}

View File

@ -23,10 +23,10 @@
/*
* @test
* @bug 8326458
* @bug 8326458 8155030
* @key headful
* @requires (os.family == "windows")
* @modules java.desktop/com.sun.java.swing.plaf.windows
* @modules java.desktop/sun.swing
* @summary Verifies if menu mnemonics toggle on F10 press in Windows LAF
* @run main TestMenuMnemonic
*/
@ -43,7 +43,7 @@ import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import sun.swing.MnemonicHandler;
public class TestMenuMnemonic {
@ -93,7 +93,7 @@ public class TestMenuMnemonic {
MenuSelectionManager msm =
MenuSelectionManager.defaultManager();
MenuElement[] selectedPath = msm.getSelectedPath();
if (WindowsLookAndFeel.isMnemonicHidden()) {
if (MnemonicHandler.isMnemonicHidden()) {
mnemonicHideCount.getAndIncrement();
// Check if selection is cleared when mnemonics are hidden
if (selectedPath.length != 0) {

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/*
* @test
* @bug 8155030
* @key headful
* @requires (os.family == "linux" | os.family == "mac")
* @library /javax/swing/regtesthelpers
* @build Util
* @summary Verifies if menu mnemonic toggle on Alt press in GTK and Aqua LAF
* @run main TestMenuMnemonicLinuxAndMac
*/
public class TestMenuMnemonicLinuxAndMac {
private static JFrame frame;
private static JMenu fileMenu;
private static volatile Rectangle fileMenuRect;
public static void main(String[] args) throws Exception {
for (UIManager.LookAndFeelInfo laf :
UIManager.getInstalledLookAndFeels()) {
if (laf.getName().contains("GTK") || laf.getName().contains("Aqua")) {
System.out.println("Testing: " + laf.getName());
UIManager.setLookAndFeel(laf.getClassName());
break;
}
}
Robot robot = new Robot();
robot.setAutoDelay(200);
try {
SwingUtilities.invokeAndWait(TestMenuMnemonicLinuxAndMac::createAndShowUI);
robot.waitForIdle();
robot.delay(1000);
SwingUtilities.invokeAndWait(() -> {
fileMenuRect = new Rectangle(fileMenu.getLocationOnScreen(),
fileMenu.getSize());
});
robot.keyPress(KeyEvent.VK_ALT);
robot.waitForIdle();
BufferedImage img1 = robot.createScreenCapture(fileMenuRect);
robot.keyRelease(KeyEvent.VK_ALT);
robot.waitForIdle();
BufferedImage img2 = robot.createScreenCapture(fileMenuRect);
if (Util.compareBufferedImages(img1, img2)) {
try {
ImageIO.write(img1, "png", new File("Menu_With_Mnemonic.png"));
ImageIO.write(img2, "png", new File("Menu_Without_Mnemonic.png"));
} catch (IOException ignored) {
}
throw new RuntimeException("Mismatch in mnemonic show/hide on Alt press");
}
} finally {
SwingUtilities.invokeAndWait(() -> {
if (frame != null) {
frame.dispose();
}
});
}
}
private static void createAndShowUI() {
frame = new JFrame("Test Menu Mnemonic Show/Hide");
JMenuBar menuBar = new JMenuBar();
fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
JMenuItem item1 = new JMenuItem("Item-1");
JMenuItem item2 = new JMenuItem("Item-2");
fileMenu.add(item1);
fileMenu.add(item2);
menuBar.add(fileMenu);
frame.setJMenuBar(menuBar);
frame.setSize(250, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,10 +23,10 @@
/*
* @test
* @bug 4736093
* @bug 4736093 8155030
* @requires (os.family == "windows")
* @summary REGRESSION: Menu and controls shortcuts are not visible in Win L&F in jdk1.4.1
* @modules java.desktop/com.sun.java.swing.plaf.windows
* @modules java.desktop/sun.swing
* @key headful
*/
@ -42,7 +42,7 @@ import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import sun.swing.MnemonicHandler;
public class bug4736093 {
static volatile boolean passed = true;
@ -62,7 +62,7 @@ public class bug4736093 {
winlaf = false;
}
if (winlaf && WindowsLookAndFeel.isMnemonicHidden()) {
if (winlaf && MnemonicHandler.isMnemonicHidden()) {
mainFrame = new JFrame("Bug 4736093");
mainFrame.addWindowListener(new TestStateListener());
mainFrame.setSize(200, 400);
@ -100,7 +100,7 @@ public class bug4736093 {
public static void checkForMnemonics(boolean expected) {
if (expected != WindowsLookAndFeel.isMnemonicHidden()) {
if (expected != MnemonicHandler.isMnemonicHidden()) {
passed = false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,14 +24,13 @@
/**
* @test
* @key headful
* @bug 6921687 8079428
* @bug 6921687 8079428 8155030
* @summary Mnemonic disappears after repeated attempts to open menu items using
* mnemonics
* @author Semyon Sadetsky
* @library /test/lib
* @build jdk.test.lib.Platform
* @requires (os.family == "windows")
* @modules java.desktop/com.sun.java.swing.plaf.windows
* @modules java.desktop/sun.swing
* @run main bug6921687
*/
@ -45,6 +44,8 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import jdk.test.lib.Platform;
import sun.swing.MnemonicHandler;
public class bug6921687 {
private static Class lafClass;
@ -91,7 +92,7 @@ public class bug6921687 {
}
private static void checkMnemonics() throws Exception {
if ((Boolean) lafClass.getMethod("isMnemonicHidden").invoke(lafClass)) {
if (MnemonicHandler.isMnemonicHidden()) {
throw new RuntimeException("Mnemonics are hidden");
}
}